Подтвердить что ты не робот

Закругленный прогресс в пределах округленного индикатора выполнения

Я пытаюсь создать пользовательский индикатор выполнения в приложении, над которым мы работаем, и последний элемент, который мне нужен, - это индикатор прогресса. Вместо этого я хочу, чтобы этот бар был закруглен точно так же, как левый и правый края самого индикатора выполнения, как на втором изображении (за вычетом красного круга, конечно).

enter image description here

enter image description here

Здесь определение макета индикатора выполнения (остальная часть файла макета опущена для краткости):

<ProgressBar
    android:id="@+id/progress_bar"
    android:layout_width="fill_parent"
    android:layout_height="60dp"
    android:padding="3dp"
    android:max="100"
    android:progressDrawable="@drawable/progress_bar_states"
    android:layout_marginTop="10dp"
    style="?android:attr/progressBarStyleHorizontal"
    android:indeterminateOnly="false"
    android:layout_below="@id/textview2"
    android:layout_alignLeft="@id/textview2"
    />

и вот файл progress_bar_states.xml:

<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">
        <clip>
            <shape>
                <solid android:color="#20ffffff"/>
                <corners android:radius="60dp"/>
            </shape>
        </clip>
    </item>

</layer-list>

Как мне это сделать? Я не вижу никаких параметров, позволяющих мне определить индикатор прогресса вообще. Должен ли я делать это по-другому? Я все еще довольно новичок в Android, поэтому любое руководство ценится.

@Ando - ваше решение очень близко к тому, что мне нужно. Сейчас начинается движение индикатора, и я предполагаю, что это не клип, как оригинал. Когда индикатор начинается и до некоторой точки в начале, похоже, что он "сжат"

enter image description here

пока он не попадет в соответствующую точку, тогда он выглядит нормально:

enter image description here

Как мы можем выполнить "отсечение" с самого начала с помощью этого решения?

Для @bladefury - как вы можете видеть, по сравнению с передним краем изображения выше, он кажется сплющенным.

enter image description here

EDIT: не смотря на это довольно долгое время, я посмотрел на новый компонент https://github.com/akexorcist/Android-RoundCornerProgressBar/issues, и он имеет тот же как предложения здесь.

4b9b3361

Ответ 1

Вы можете использовать эту библиотеку для полосы выполнения закругленного угла

<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

Ответ 2

просто измените файл progress_bar_states.xml: как показано ниже.

<?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>

здесь custom_progress_primary.xml файл: как ниже

<?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>

Ответ 3

Опция, которая, возможно, более практична, реализует пользовательский вид панели выполнения.

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

    }
}

Затем в вашем макете:

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

Что дает результат:

Результат пользовательской последовательности выполнения

Ответ 4

ProgressBar использует ClipDrawable, который позволяет клинировать с прямоугольником. Таким образом, вы можете установить drawable, который скопирует круглый прямоугольник угла в индикатор выполнения, и вот как:

во-первых, удалите тег <clip> в вашем индикаторе выполнения:

<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>

затем увеличьте индикатор выполнения следующим образом:

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;
    }

}

и здесь RoundClipDrawable, измененный от ClipDrawable:

RoundClipDrawable.java Gist

Ответ 5

вы также можете использовать эту кнопку для поиска

проверить мой пост здесь: fooobar.com/questions/311409/...

Попробуйте это, вы можете сделать то, что хотите, изменив цвет, ширину и высоту большого пальца и строку поиска в xml.

Ответ 6

Как мы можем выполнить "отсечение" с самого начала с помощью этого решения?

Вам нужно ограничить минимальное значение прогресса, например:

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

Используйте вышеприведенный код для постпроцесса вашего значения прогресса. Это не удобочитаемая ошибка, а правильный эффект растяжения.