I have been trying to implement a bar showing progress data with ConstraintLayout. The problem is my TextView goes out of the layout bound when the Guideline is too left or too right of the bar.
I have tried to change the constraints of the TextView from connected to the "@id/guideline" into "parent", and add horizontalBias instead, but then the TextView will become inaccurately positioned (a little shifted to right/left side depends on the yellow bar length)
Here is the image of current result:
Here is the layout code:
<android.support.constraint.ConstraintLayout
android:id="@+id/layoutConstraint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingLeft="16dp"
android:paddingTop="100dp"
android:paddingRight="16dp"
android:paddingBottom="16dp">
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".01" />
<TextView
android:id="@+id/textProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="12dp"
android:textColor="@color/black"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="@id/guideline"
app:layout_constraintStart_toStartOf="@id/guideline"
app:layout_constraintTop_toTopOf="parent"
tools:text="current value" />
<View
android:id="@+id/layoutProgress"
android:layout_width="0dp"
android:layout_height="8dp"
android:background="@drawable/background_rounded_corner_light_grey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textProgress" />
<View
android:id="@+id/currentProgress"
android:layout_width="0dp"
android:layout_height="8dp"
android:background="@drawable/background_rounded_corner_yellow"
app:layout_constraintEnd_toStartOf="@id/guideline"
app:layout_constraintStart_toStartOf="@id/layoutProgress"
app:layout_constraintTop_toBottomOf="@id/textProgress" />
</android.support.constraint.ConstraintLayout>
It looks like you want to keep the text "current value" centered on the end of the progress bar; however, if this placement causes the text to be cutoff on either the left side or the right, the text should be aligned to the side of the ConstraintLayout
so that it remains entirely visible.
Your TextView
is centered on the percentage guideline that you position programmatically between 0% and 100% (I assume.)
I suggest that you change the guideline to one based upon pixels (dp or px) and position your TextView
that is centered on the new guideline. Instead of varying the guideline position from zero to 100%, calculated a new range:
Low end of range = 1/2 the width of TextView
plus whatever margin.
High end of range = width of the ConstraintLayout
- 1/2 width of the TextView
minus whatever margin.
The margin will remain at the low end of the range while progress falls to the left of the low end. As the progress goes past the low end, the guideline will move to the right by the current location of the progress bar - the low end. The guideline will stop at the high end as progress continues on to 100%.
If you want to stick with the percentage guideline, compute the low and high ends as outlined above. You can then compute the low and high percentages based upon the width of the container.
Here is a short demo that uses a simple block for progress:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ConstraintLayout mLayout;
private View mProgress;
private int mProgressPosition;
private int mGuidelineMin;
private int mGuidelineMax;
private Guideline mGuideline;
private int mIncrement;
private Handler mHandler = new Handler();
private int mMargin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout = findViewById(R.id.layout);
mGuideline = findViewById(R.id.guideline);
mProgress = findViewById(R.id.progress);
mMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 16,
getResources().getDisplayMetrics()
);
mLayout.post(new Runnable() {
private int mLoopCount = 100;
@Override
public void run() {
int textWidth = findViewById(R.id.textView).getWidth();
mGuidelineMin = textWidth / 2 + mMargin;
mGuidelineMax = mLayout.getWidth() - textWidth / 2 - mMargin;
mGuideline.setGuidelineBegin(mGuidelineMin);
mIncrement = (mLayout.getWidth() - mProgress.getWidth()) / mLoopCount;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mProgressPosition += mIncrement;
mProgress.setTranslationX(mProgressPosition);
int guidelinePosition =
Math.max(mGuidelineMin, mProgressPosition + mProgress.getWidth() / 2);
if (guidelinePosition > mGuidelineMax) {
guidelinePosition = mGuidelineMax;
}
mGuideline.setGuidelineBegin(guidelinePosition);
if (--mLoopCount > 0) {
mHandler.postDelayed(this, 100);
}
}
}, 100);
}
});
}
}
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/progress"
android:layout_width="15dp"
android:layout_height="15dp"
android:background="@android:color/holo_red_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.17" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Current value"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.07999998" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="140dp" />
</androidx.constraintlayout.widget.ConstraintLayout>