有没有办法在进度条中放置分隔线?

Is there a way to put a separator line in the progress bar?

在开发Android的时候,有一个任务需要在Progress Bar中划一条分界线,如下图

但是我实现的Progress Bar是这样的

我制作的进度条由以下代码组成

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <solid android:color="#D1D1D6" />
            <size android:height="20dp" />
            <corners android:radius="12dp" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape android:shape="rectangle">
                <solid android:color="#26B477" />
                <size android:height="20dp" />
                <corners android:radius="12dp" />
            </shape>
        </clip>
    </item>
</layer-list>

如上实现的drawable文件中的custom_seekbar.xml使用如下

<ProgressBar
    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
    android:id="@+id/todayGage"
    android:layout_width="0dp"
    android:layout_height="20dp"
    android:layout_marginStart="12dp"
    android:layout_marginLeft="12dp"
    android:layout_marginEnd="25dp"
    android:layout_marginRight="25dp"
    android:max="100"
    android:paddingStart="0dp"
    android:paddingLeft="0dp"
    android:paddingEnd="0dp"
    android:paddingRight="0dp"
    android:progressDrawable="@drawable/custom_seekbar"
    app:layout_constraintBottom_toBottomOf="@id/todayPercent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/todayPercent"
    app:layout_constraintTop_toTopOf="@id/todayPercent" />

有没有办法像我想要的那样在进度条内设置分界线??

韩吉曼你好

我会建议你举两个例子

第一个

    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.os.CountDownTimer;
 
    import android.widget.ProgressBar;

    public class MainLayout extends Activity {
      int progress=1;
      ProgressBar progressBar;
      @SuppressLint("ResourceType")
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         progressBar= (ProgressBar)findViewById(R.id.progress_bar_test);
      SeperatedProgressbar bgProgress= new SeperatedProgressbar(ContextCompat.getColor(this,R.color.color_progress),ContextCompat.getColor(this,R.color.color_normal),this);
       progressBar.setProgressDrawable(bgProgress);
        progressBar.setMax(100);
        progressBar.setProgress(50);

        new CountDownTimer(100000, 1000) {

          public void onTick(long millisUntilFinished) {
              progress=progress+1;
              progressBar.setProgress(progress);
          }

          public void onFinish() {

          }

        }.start();



      }
    }

activity_main.xml

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="match_parent"
        android:paddingLeft="10dp"
        android:layout_height="match_parent"
        >

       <ProgressBar
           android:id="@+id/progress_bar_test"
           android:layout_width="match_parent"
           android:layout_height="25dp"
           android:layout_centerInParent="true"
           style="?android:attr/progressBarStyleHorizontal"
           android:max="100"
           android:progress="10"

           />

    </RelativeLayout>

SeperatedProgressbar.java

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.ColorFilter;
    import android.graphics.Paint;
    import android.graphics.PixelFormat;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.graphics.drawable.Drawable;

    public class SeperatedProgressbar extends Drawable {
      private static final int NUM_SEGMENTS = 8;
      private int mForeground;
      private  int mBackground;
      private final Paint mPaint = new Paint();
      private final RectF mSegment = new RectF();
      Context context;

      public SeperatedProgressbar(int fgColor, int bgColor, Context context) {
        mForeground = fgColor;
        this.context=context;
        mBackground = bgColor;
      }

      @Override
      protected boolean onLevelChange(int level) {
        invalidateSelf();
        return true;
      }

      @Override
      public void draw(Canvas canvas) {
        float level = getLevel() / 1000f;
        Rect b = getBounds();
        float gapWidth = b.height() / 8f;
        float segmentWidth = (b.width() - (NUM_SEGMENTS - 1) * gapWidth) / NUM_SEGMENTS;
        mSegment.set(0, 0, segmentWidth, b.height());
        mPaint.setColor(mForeground);

        for (int i = 0; i < NUM_SEGMENTS; i++) {
          float loLevel = i / (float) NUM_SEGMENTS;
          float hiLevel = (i + 1) / (float) NUM_SEGMENTS;
          if (loLevel <= level && level <= hiLevel) {
            float middle = mSegment.left + NUM_SEGMENTS * segmentWidth * (level - loLevel);
            canvas.drawRect(mSegment.left, mSegment.top, middle, mSegment.bottom, mPaint);
            mPaint.setColor(mBackground);
          canvas.drawRect(middle, mSegment.top, mSegment.right, mSegment.bottom, mPaint);

          } else {
            canvas.drawRect(mSegment, mPaint);
          }
          mSegment.offset(mSegment.width() + gapWidth, 0);
        }
      }

      @Override
      public void setAlpha(int alpha) {
      }

      @Override
      public void setColorFilter(ColorFilter cf) {
      }

      @Override
      public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
      }
    }

结果

第二个答案

MainActivity.Java

import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;

import com.rachitgoyal.segmented.SegmentedProgressBar;

import java.util.ArrayList;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    SegmentedProgressBar mSegmentedProgressBar;
   ArrayList<Integer> arrayList=new ArrayList<>();;
    int progress;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSegmentedProgressBar = findViewById(R.id.segmented_pb_1);
        arrayList.add(progress);


        new CountDownTimer(200000, 2000) {

            public void onTick(long millisUntilFinished) {

                if(progress==0)
                {
                   
                    arrayList.add(progress);
                }
                else
                {
                    arrayList.add(progress);
                }
                progress=progress+1;

                mSegmentedProgressBar.setEnabledDivisions(arrayList);
            }

            public void onFinish() {

            }

        }.start();






    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">





    <com.test.package.SegmentedProgressBar
        android:id="@+id/segmented_pb_1"
        android:layout_width="wrap_content"
        android:layout_height="30dp"

        android:layout_centerHorizontal="true"
        android:layout_margin="10dp"
        android:layout_centerInParent="true"
        app:cornerRadius="20dp"
        app:dividerColor="@color/white"
        app:dividerWidth="2dp"
        app:divisions="10"
        app:isDividerEnabled="true"
        app:progressBarBackgroundColor="#dadada"
        app:progressBarColor="#ff2d2d" />



</RelativeLayout>

SegmentedProgressBar.java

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.os.Build;
    import android.support.v4.content.ContextCompat;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewTreeObserver;

    import com.test.package.segmentedprogressbar.R;

    import java.util.ArrayList;
    import java.util.List;


    public class SegmentedProgressBar extends View {

        private static final String TAG = "SegmentedProgressBar";
        RectF bgRect;
        private Paint progressBarBackgroundPaint = new Paint();
        private Paint progressBarPaint = new Paint();
        private Paint dividerPaint = new Paint();
        private int progressBarWidth;
        private float percentCompleted;
        private float dividerWidth = 1;
        private boolean isDividerEnabled = true;
        private int divisions = 1;
        private List<Integer> enabledDivisions = new ArrayList<>();
        private List<Float> dividerPositions;
        private float cornerRadius = 20f;

        public SegmentedProgressBar(Context context) {
            super(context);
            init(null);
        }

        private void init(AttributeSet attrs) {
            dividerPositions = new ArrayList<>();
            cornerRadius = 0;

            TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.SegmentedProgressBar, 0, 0);

            try {
                dividerPaint.setColor(typedArray.getColor(R.styleable.SegmentedProgressBar_dividerColor,
                        ContextCompat.getColor(getContext(), R.color.white)));
                progressBarBackgroundPaint.setColor(typedArray.getColor(R.styleable.SegmentedProgressBar_progressBarBackgroundColor,
                        ContextCompat.getColor(getContext(), R.color.grey_light)));
                progressBarPaint.setColor(typedArray.getColor(R.styleable.SegmentedProgressBar_progressBarColor,
                        ContextCompat.getColor(getContext(), R.color.progress_bar)));
                dividerWidth = typedArray.getDimension(R.styleable.SegmentedProgressBar_dividerWidth, dividerWidth);
                isDividerEnabled = typedArray.getBoolean(R.styleable.SegmentedProgressBar_isDividerEnabled, true);
                divisions = typedArray.getInteger(R.styleable.SegmentedProgressBar_divisions, divisions);
                cornerRadius = typedArray.getDimension(R.styleable.SegmentedProgressBar_cornerRadius, 2f);

            } finally {
                typedArray.recycle();
            }

            ViewTreeObserver viewTreeObserver = getViewTreeObserver();
            if (viewTreeObserver.isAlive()) {
                viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        if (getWidth() > 0) {
                            getViewTreeObserver().removeOnGlobalLayoutListener(this);
                            progressBarWidth = getWidth();
                            dividerPositions.clear();
                            if (divisions > 1) {
                                for (int i = 1; i < divisions; i++) {
                                    dividerPositions.add(((float) (progressBarWidth * i) / divisions));
                                }
                            }
                            bgRect = new RectF(0, 0, getWidth(), getHeight());
                            updateProgress();
                        }
                    }
                });
            }
        }

        /**
         * Updates the progress bar based on manually passed percent value.
         */
        private void updateProgress() {
            invalidate();
        }

        public SegmentedProgressBar(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(attrs);
        }

        public SegmentedProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(attrs);
        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public SegmentedProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init(attrs);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            if (bgRect != null) {

                canvas.drawRoundRect(bgRect, cornerRadius, cornerRadius, progressBarBackgroundPaint);

                for (Integer enabledDivision : enabledDivisions) {
                    if (enabledDivision < divisions) {
                        float left = 0;
                        if (enabledDivision != 0) {
                            left = dividerPositions.get(enabledDivision - 1) + dividerWidth;
                        }
                        float right = enabledDivision >= dividerPositions.size() ? progressBarWidth : dividerPositions.get(enabledDivision);

                        RectF rect = new RectF(left, 0, right, getHeight());
                        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, progressBarPaint);
                        if (enabledDivision == 0) {
                            canvas.drawRect(left + cornerRadius, 0, right, getHeight(), progressBarPaint);
                        } else if (enabledDivision == divisions - 1) {
                            canvas.drawRect(left, 0, right - cornerRadius, getHeight(), progressBarPaint);
                        } else {
                            canvas.drawRect(rect, progressBarPaint);
                        }
                    }

                    if (divisions > 1 && isDividerEnabled) {
                        for (int i = 1; i < divisions; i++) {
                            float leftPosition = dividerPositions.get(i - 1);
                            canvas.drawRect(leftPosition, 0, leftPosition + dividerWidth, getHeight(), dividerPaint);
                        }
                    }
                }
            }
        }

        /**
         * Set the color for the progress bar background
         *
         * @param color
         */
        public void setBackgroundColor(int color) {
            progressBarBackgroundPaint.setColor(color);
        }

        public void reset() {
            dividerPositions.clear();
            percentCompleted = 0;
            updateProgress();
        }

        /**
         * Set the color for the progress bar
         *
         * @param color
         */
        public void setProgressBarColor(int color) {
            progressBarPaint.setColor(color);
        }

        /**
         * Set the color for the divider bar
         *
         * @param color
         */
        public void setDividerColor(int color) {
            dividerPaint.setColor(color);
        }

        /**
         * set the width of the divider
         *
         * @param width
         */
        public void setDividerWidth(float width) {
            if (width < 0) {
                Log.w(TAG, "setDividerWidth: Divider width can not be negative");
                return;
            }
            dividerWidth = width;
        }

        /**
         * Set whether the dividers are enabled or not.
         *
         * @param value true or false
         */
        public void setDividerEnabled(boolean value) {
            isDividerEnabled = value;
        }

        /**
         * Sets the number of divisions in the ProgressBar.
         *
         * @param divisions number of divisions
         */
        public void setDivisions(int divisions) {
            if (divisions < 1) {
                Log.w(TAG, "setDivisions: Number of Divisions cannot be less than 1");
                return;
            }
            this.divisions = divisions;
            dividerPositions.clear();
            if (divisions > 1) {
                for (int i = 1; i < divisions; i++) {
                    dividerPositions.add(((float) (progressBarWidth * i) / divisions));
                }
            }
            updateProgress();
        }

        /**
         * Set the enabled divisions to specified value.
         *
         * @param enabledDivisions number of divisions to be enabled
         */
        public void setEnabledDivisions(List<Integer> enabledDivisions) {
            this.enabledDivisions = enabledDivisions;
            updateProgress();
        }

        public void setCornerRadius(float cornerRadius) {
            this.cornerRadius = cornerRadius;
        }
    }

attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="SegmentedProgressBar">
            <attr name="dividerColor" format="color" />
            <attr name="progressBarBackgroundColor" format="color" />
            <attr name="progressBarColor" format="color" />
            <attr name="dividerWidth" format="dimension" />
            <attr name="isDividerEnabled" format="boolean" />
            <attr name="divisions" format="integer" />
            <attr name="cornerRadius" format="dimension" />
        </declare-styleable>
    </resources>

回应