Reputation: 536
I am going to implement a progress bar with two clip textview on it.
Something like:
I use some trick (using paddingEnd/paddingStart, back/front textview to achieve the clip effect for textview) to implement it:
// part of activity
TextView leftFrontText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = View.inflate(this, R.layout.test_page_layout, containerLayout);
View progressBar = view.findViewById(R.id.progress_bar);
leftFrontText = view.findViewById(R.id.left_front_textview);
int progress = 59;
ValueAnimator va = ValueAnimator.ofFloat(0f, progress);
int mDuration = 1000;
va.setDuration(mDuration);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float)animation.getAnimatedValue();
setViewWidth(progressBar, (int)value);
setLeftFrontTextViewPadding((int)value);
}
});
// va.addListener(new Animator.AnimatorListener() {
// @Override
// public void onAnimationStart(Animator animation) {
//
// }
//
// @Override
// public void onAnimationEnd(Animator animation) {
// setLeftFrontTextViewPadding(progress);
// }
//
// @Override
// public void onAnimationCancel(Animator animation) {
//
// }
//
// @Override
// public void onAnimationRepeat(Animator animation) {
//
// }
// });
va.start();
}
private void setViewWidth(View view, int dp) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = ThemeUtil.dpToPx(this, dp);
view.setLayoutParams(layoutParams);
}
private void setLeftFrontTextViewPadding(int progressBarDp) {
int marginStart = ThemeUtil.dpToPx(TestPageActivity.this, 12);
leftFrontText.post(new Runnable() {
@Override
public void run() {
int textViewLength = leftFrontText.getWidth();
int progressbarDistance = ThemeUtil.dpToPx(TestPageActivity.this, progressBarDp);
if (textViewLength >= 0) {
int padding = marginStart + textViewLength - progressbarDistance;
leftFrontText.setPadding(0, 0, padding > 0 ? -padding : 0, 0);
}
}
});
}
And the layout is:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="28dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/rounded_corner_bg_for_cashlfow_homepage_category_cell"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
>
<TextView
android:id="@+id/left_bottom_textview"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:gravity="center_vertical"
android:text="Entertatinment"
android:textSize="@dimen/main_text_size"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/grey1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="12dp"
/>
<View
android:id="@+id/progress_bar"
android:layout_width="10dp"
android:layout_height="match_parent"
android:background="@drawable/rounded_corner_front_progreebar_homepage_category_cell"
app:layout_constraintStart_toStartOf="parent"
/>
<TextView
android:id="@+id/left_front_textview"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:gravity="center_vertical|start"
android:text="Entertatinment"
android:textSize="@dimen/main_text_size"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="12dp"
/>
<TextView
android:id="@+id/right_bottom_amount_textview"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:gravity="center_vertical|end"
android:text="$0 / $0"
android:textSize="@dimen/main_text_size"
android:maxLines="1"
android:textColor="@color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="12dp"
/>
<TextView
android:id="@+id/right_front_amount_textview"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:gravity="center_vertical|end"
android:text="$0 / $0"
android:textSize="@dimen/main_text_size"
android:maxLines="1"
android:textColor="@color/black1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="12dp"
android:paddingStart="0dp"
/>
</android.support.constraint.ConstraintLayout>
When I run this code, it almost achieved the effect I want. But it has one issue. Textview keeps flashing while doing animation, and when animation finished, the color of textview sometime turn all white.
I think there may be something wrong in leftFrontText.post()
of setLeftFrontTextViewPadding
, like how I get width of textview. But I can't be quite sure. Can anyone show me the right way to do this? Or any other better way to implement this kind of progress bar.
Upvotes: 4
Views: 367
Reputation: 4658
Why not try this approach and leverage the power of ConstraintLayout
as your progressBar:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parentview"
android:layout_width="360dp"
android:layout_height="28dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#ddddff"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp">
<TextView
android:id="@+id/left_bottom_textview"
android:layout_width="180dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="Entertainment"
android:maxLines="1"
android:ellipsize="end"
android:textColor="#404040"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/right_front_amount_textview"
android:layout_width="180dp"
android:layout_height="0dp"
android:gravity="center_vertical|end"
android:text="$0 / $0"
android:maxLines="1"
android:textColor="@color/black"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<android.support.constraint.ConstraintLayout
android:id="@+id/progress_bar"
android:layout_width="50dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
android:background="#004090">
<TextView
android:id="@+id/left_front_textview"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="Entertainment"
android:singleLine="true"
android:textColor="#fff"
android:ellipsize="none"
android:layout_paddingStart="12dp"
android:layout_paddingLeft="12dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/right_bottom_amount_textview"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="center_vertical|end"
android:text="$0 / $0"
android:layout_alignRight="@id/left_front_textview"
android:textColor="#ffffff"
android:layout_paddingEnd="12dp"
android:layout_paddingRight="12dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/left_front_textview"/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
So basically we would have:
The Parent layout (parentview): having a fixed layout_width 360dp
and contains the initial Grey TextViews
The Progress layout (progress_bar): also having a fixed size 360dp
and contains the front White TextViews
Hence we overlay the Progress layout (progress_bar)
ontop of its parent layout and increase or decrease the layout_width
to simulate a progress without flickering:
The image below shows the progress layout having a static layout_width of 74dp
; Also note that progress layout_width
based on the example provided above can range from 1dp to max:360dp
or otherwise 1% to 100% of parentview width
.
Upvotes: 1