Android实现一个progressBar,上面有两个剪辑textview

Posted

技术标签:

【中文标题】Android实现一个progressBar,上面有两个剪辑textview【英文标题】:Android implement a progressBar with two clip textview on it 【发布时间】:2019-08-19 11:14:41 【问题描述】:

我将实现一个带有两个剪辑文本视图的进度条。 就像是:

我使用了一些技巧(使用paddingEnd/paddingStart,back/front textview来实现textview的剪辑效果)来实现它:

    // 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);
                
            
        );

    

而布局是:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    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_
        android:layout_
        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_
        android:layout_
        android:background="@drawable/rounded_corner_front_progreebar_homepage_category_cell"
        app:layout_constraintStart_toStartOf="parent"
        />

    <TextView
        android:id="@+id/left_front_textview"
        android:layout_
        android:layout_
        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_
        android:layout_
        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_
        android:layout_
        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>

当我运行这段代码时,它几乎达到了我想要的效果。但它有一个问题。 Textview 在做动画的时候一直在闪烁,当动画完成时,textview 的颜色有时会变成全白。

我认为setLeftFrontTextViewPadding 中的leftFrontText.post() 可能有问题,比如我如何获得 textview 的宽度。但我不能确定。谁能告诉我这样做的正确方法?或者任何其他更好的方式来实现这种进度条。

【问题讨论】:

【参考方案1】:

为什么不尝试这种方法并利用ConstraintLayout 的强大功能作为您的进度条:

<?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_
    android:layout_
    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_
        android:layout_
        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_
        android:layout_
        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_
        android:layout_
        app:layout_constraintStart_toStartOf="parent" 
        android:background="#004090">
        <TextView
            android:id="@+id/left_front_textview"
            android:layout_
            android:layout_
            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_
            android:layout_
            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>

所以基本上我们会:

父布局(父视图):具有固定的 layout_width 360dp 并包含初始 Grey TextViews

进度布局(progress_bar):也有固定大小360dp并包含前面White TextViews

因此,我们将Progress layout (progress_bar) 覆盖在其父布局的顶部,并增加或减少layout_width 以模拟没有闪烁的进度:

下图显示了静态 layout_width 为74dp 的进度布局;另请注意,基于上述示例的progress layout_width 的范围可以是1dp to max:360dp1% to 100% of parentview width

【讨论】:

以上是关于Android实现一个progressBar,上面有两个剪辑textview的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义ProgressBar,实现漂亮的进度提示框

Android 三种方式实现自定义圆形进度条ProgressBar

android recyclerView嵌套progressbar

delphi xe android 更改ProgressBar1进度条颜色

Android中的常用控件之进度条(ProgressBar)

Android ProgressBar具体解释以及自己定义