Rounded progress within rounded progress bar

北战南征 提交于 2019-11-29 01:23:24

You can use this library for rounded corner progress bar

<com.akexorcist.roundcornerprogressbar.RoundCornerProgressBar
        android:layout_width="dimension"
        android:layout_height="dimension"
        app:rcProgress="float"
        app:rcSecondaryProgress="float"
        app:rcMax="float"
        app:rcRadius="dimension"
        app:rcBackgroundPadding="dimension"
        app:rcReverse="boolean"
        app:rcProgressColor="color"
        app:rcSecondaryProgressColor="color"
        app:rcBackgroundColor="color" />

Gradle

compile 'com.akexorcist:RoundCornerProgressBar:2.0.3'

https://github.com/akexorcist/Android-RoundCornerProgressBar

just Change your progress_bar_states.xml file: like below example

<?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>
        <solid android:color="#20ffff00" />

        <corners android:radius="20dp" />
    </shape>
</item>
<item android:id="@android:id/progress">

    <!-- <clip> -->
    <!-- <shape> -->
    <!-- <solid android:color="@android:color/black" /> -->


    <!-- <corners -->
    <!-- android:bottomRightRadius="30dp" -->
    <!-- android:radius="60dp" -->
    <!-- android:topRightRadius="30dp" /> -->
    <!-- </shape> -->
    <!-- </clip> -->

    <scale
        android:drawable="@drawable/custom_progress_primary"
        android:scaleWidth="98%" /><!-- change here -->
</item>

here custom_progress_primary.xml file: like below

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

<corners
    android:radius="20dp"
    android:topLeftRadius="20dp"
    android:topRightRadius="20dp" />

<solid android:color="@android:color/white" />

<stroke
    android:width="1dp"
    android:color="@android:color/darker_gray" />

</shape>

An option that's perhaps a bit more practical is implementing a custom Progress Bar view.

public class CustomProgressBar extends View
{
    // % value of the progressbar.
    int progressBarValue = 0;

    public CustomProgressBar(Context context)
    {
        super(context);
    }

    public CustomProgressBar(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        progressBarValue = attrs.getAttributeIntValue(null, "progressBarValue", 0);
    }

    public void setValue(int value)
    {
        progressBarValue = value;
        invalidate();
    }

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

        float cornerRadius = 30.0f;

        // Draw the background of the bar.
        Paint backgroundPaint = new Paint();
        backgroundPaint.setColor(Color.LTGRAY);
        backgroundPaint.setStyle(Paint.Style.FILL);
        backgroundPaint.setAntiAlias(true);

        RectF backgroundRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
        canvas.drawRoundRect(backgroundRect, cornerRadius, cornerRadius, backgroundPaint);

        // Draw the progress bar.
        Paint barPaint = new Paint();
        barPaint.setColor(Color.GREEN);
        barPaint.setStyle(Paint.Style.FILL);
        barPaint.setAntiAlias(true);

        float progress = (backgroundRect.width() / 100) * progressBarValue;
        RectF barRect = new RectF(0, 0, progress, canvas.getClipBounds().bottom);

        canvas.drawRoundRect(barRect, cornerRadius, cornerRadius, barPaint);

        // Draw progress text in the middle.
        Paint textPaint = new Paint();
        textPaint.setColor(Color.WHITE);
        textPaint.setTextSize(34);

        String text = progressBarValue + "%";
        Rect textBounds = new Rect();

        textPaint.getTextBounds(text, 0, text.length(), textBounds);

        canvas.drawText(text,
                backgroundRect.centerX() - (textBounds.width() / 2),
                backgroundRect.centerY() + (textBounds.height() / 2),
                textPaint);

    }
}

Then in your layout:

<view.CustomProgressBar
    android:layout_height="30dp"
    android:layout_width="match_parent"
    progressBarValue="66"/>

Which yields the result:

ProgressBar uses ClipDrawable, which clips drawable with a rectangle. So, you can set a drawable which clips round corner rectangle to progress bar, and here's how:

first, remove <clip> tag in your progress bar drawable:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@android:id/background">
    <shape>
        <solid android:color="#20ffff00"/>
        <corners android:radius="60dp"/>
    </shape>
</item>

<item android:id="@android:id/progress">
        <shape>
            <solid android:color="#20ffffff"/>
            <corners android:radius="60dp"/>
        </shape>
</item>

then, extend progress bar like this:

public class RoundIndicatorProgressBar extends ProgressBar {

    private static final float CORNER_RADIUS_DP = 60.0f;

    public RoundIndicatorProgressBar(Context context) {
        this(context, null);
    }

    public RoundIndicatorProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundIndicatorProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }


    @Override
    public void setProgressDrawable(Drawable d) {
        super.setProgressDrawable(tileify(d, false));
    }

    private Drawable tileify(Drawable drawable, boolean clip) {
        if (drawable instanceof LayerDrawable) {
            LayerDrawable background = (LayerDrawable) drawable;
            final int N = background.getNumberOfLayers();
            Drawable[] outDrawables = new Drawable[N];

            for (int i = 0; i < N; i++) {
                int id = background.getId(i);
                outDrawables[i] = tileify(background.getDrawable(i),
                        (id == android.R.id.progress || id == android.R.id.secondaryProgress));
            }

            LayerDrawable newBg = new LayerDrawable(outDrawables);

            for (int i = 0; i < N; i++) {
                newBg.setId(i, background.getId(i));
            }

            return newBg;

        } else {
            if (clip) {
                return new RoundClipDrawable(drawable, dp2px(getContext(), CORNER_RADIUS_DP));
            }
        }
        return drawable;
    }
    public static float dp2px(Context context, float dp) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return dp * scale;
    }

}

and here is RoundClipDrawable, modified from ClipDrawable:

RoundClipDrawable.java Gist

iDeveloper

you can use seekbar for this too

check my post here : https://stackoverflow.com/a/41206481/6033946

Try this , you may be able to do what you want by modifying the color and width and height of the thumb and the seekbar in xml.

How do we accomplish the 'clipping' at the start with this solution?

What you need is to limit the min progress value, like:

final int minProgress = pb.getMax() * {20dp} / pb.getWidth();
progress = Math.max(minProgress, progress);
pb.setProgress(progress);

Use code above to postprocess your progress value is ok. It is not a drawable bug, but a right stretch effect.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!