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

17

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

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

<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 - ваше решение очень близко к тому, что мне нужно. Сейчас начинается движение индикаторов, и я предполагаю, что это не клип, как оригинал. Когда индикатор начинается и до некоторой точки в начале, похоже, что он «сжат»

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

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

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

EDIT: не смотря на это довольно долгое время, я посмотрел новый компонент на Ссылка , и он имеет ту же проблему, что и предложения здесь.

    
задан TheIcemanCometh 05.08.2014 в 04:36
источник
  • Я не понимаю вашу озабоченность. android: progress=".." должен работать нормально. Вы также можете установить значение «неопределенный», –  harvey_slash 05.08.2014 в 04:58
  • Я не говорю об увеличении прогресса - я говорю о представлении прогресса. Вместо того, чтобы прогресс был вертикальным «баром», как вы обычно видите в индикаторе прогресса, я хочу, чтобы он был округленным индикатором, чтобы соответствовать тому, как выглядят внешние границы панели. Я попытаюсь обновить вопрос с изображением того, как я хочу, чтобы он выглядел. –  TheIcemanCometh 05.08.2014 в 12:16

6 ответов

0

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

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

Ссылка

    
ответ дан Aditya Vyas-Lakhan 07.03.2017 в 12:37
25

просто измените файл 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>
    
ответ дан Ando Masahashi 05.08.2014 в 13:07
  • Это очень близко, но есть небольшая проблема в начале движения индикатора. Я опубликовал пару изображений в исходном вопросе, чтобы показать это. –  TheIcemanCometh 05.08.2014 в 14:33
  • @TheIcemanCometh может попытаться использовать клип, и я пытаюсь обеспечить лучший –  Ando Masahashi 05.08.2014 в 14:45
  • проверьте мой обновленный ответ и измените размер размера индикатора выполнения, который я тестировал с 20dp как высота и радиус 20dp каждый, где @TheIcemanCometh –  Ando Masahashi 05.08.2014 в 15:10
  • @AndoMasahashi изменил масштабWidth до 96%, а затем он отлично справился со мной даже при достижении значения 1. Можете ли вы объяснить, что делает scaleWidth здесь? –  Akhil Dad 19.01.2016 в 07:25
  • @AndoMasahashi, как установить подвижный градиент загрузки? –  Akbar Begimkulov 20.10.2016 в 14:34
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"/>

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

    

ответ дан jverrijt 15.10.2016 в 11:53
  • Как установить максимальное значение прогресса? –  Naveen Kumar M 16.12.2016 в 13:37
0

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

    
ответ дан bladefury 06.08.2014 в 05:19
  • См. мои комментарии в исходном вопросе. Передний край индикатора из вашего решения кажется сплющенным ... –  TheIcemanCometh 10.08.2014 в 06:09
  • @TheIcemanCometh, конечно, он сглажен, потому что CORNER_RADIUS в RoundIndicatorProgressBar составляет 50.0f для демонстрационной цели. В вашем случае вы должны установить его на соответствующее значение. –  bladefury 10.08.2014 в 17:09
  • Вы основываете свое мнение на предположении, что я сохранил те же самые значения, которые у вас есть выше, которые я уже изменил, чтобы соответствовать моим требованиям (они везде 60dp). :-) –  TheIcemanCometh 10.08.2014 в 21:15
  • Многое, гораздо ближе. Теперь это примерно то же самое, что решение @ Ando, ​​кроме вашего, делает обрезку. Но оба решения имеют одинаковую проблему - начало индикатора прогресса. Когда прогресс начинается с нуля, и до тех пор, пока он не достигнет около 20%, он все равно будет сплющен на переднем крае индикатора. Он должен быть полностью округлен в начале - от 0% до 100%. Вот скринкаст примера приложения, которое я использую для тестирования: screencast.com/t/ifdJEJMy2. У меня также есть пример приложения на GitHub, в github.com/TheIcemanCometh/RoundedProgressSample1. –  TheIcemanCometh 11.08.2014 в 14:41
0

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

проверить мой пост здесь: Ссылка

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

    
ответ дан tahaDev 18.12.2016 в 09:17
-1
  

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

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

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

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

    
ответ дан Xavier.S 16.04.2016 в 09:32