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

В нашем приложении нам нужен неопределенный индикатор выполнения, например:

индикатор выполнения, каким он должен быть

Мы можем добиться этого, установив отрицательную маржу в ProgressBar, например:

<ProgressBar
    android:id="@+id/progressbar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    android:marginTop="-7dp"
    android:visibility="@{loading ? View.VISIBLE : View.GONE}" />

НО поскольку ConstraintLayout не поддерживает отрицательные поля, это будет выглядеть так:

индикатор выполнения с отступом

Хорошо, отрицательная маржа была хаком. Давайте заменим его другим хаком, хорошо? Давайте представим наше пользовательское представление CustomProgressBar, которое расширяет ProgressBar и переопределяет его метод onDraw, например:

@Override
protected void onDraw(Canvas canvas) {
    int marginTop = dpToPx(7);
    canvas.translate(0, -marginTop);
    super.onDraw(canvas);
}

Но все это пахнет плохим кодом. Должно быть лучшее решение! Чтобы вы посоветовали?


person mreichelt    schedule 10.11.2016    source источник


Ответы (6)


Другой способ сделать это — использовать направляющую и центрировать ProgressBar между верхней частью родительского элемента и направляющей.

<ProgressBar
    android:id="@+id/progressBar2"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="0dp"
    android:paddingTop="-4dp"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintBottom_toTopOf="@+id/guideline"
    app:layout_constraintTop_toTopOf="parent" />

<android.support.constraint.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/guideline"
    android:orientation="horizontal"
    app:layout_constraintGuide_begin="4dp" />
person hoford    schedule 11.11.2016
comment
Спасибо, это действительно помогло! Я немного изменил ответ, установив app:layout_constraintGuide_begin="9dp" в направляющей, и только установив app:layout_constraintTop_toTopOf="@+id/guideline" (без ограниченияBottom или padding) для панели прогресса — работает. Мне все еще кажется хакерским, но я считаю, что это лучший вариант на данный момент. - person mreichelt; 16.11.2016

Решение, которое меньше похоже на взлом: оберните огромное ProgressBar меньшим FrameLayout. Таким образом, FrameLayout ограничивает свою высоту, но ProgressBar по-прежнему отображается полностью.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="4dp">

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:layout_gravity="center" />

</FrameLayout>
person 0101100101    schedule 05.12.2017
comment
другое решение: ‹ProgressBar style=@style/Widget.AppCompat.ProgressBar.Horizontal android:layout_height=4dp/› - person Xan; 15.06.2018
comment
Это просто отстой, нам нужно сделать это только для чего-то такого простого. - person Archie G. Quiñones; 10.08.2018

Я столкнулся с той же проблемой. И, как вы сказали, я сталкиваюсь с многочисленными решениями, которые все кажутся взломом, который может сломать что-то еще в будущем. С учетом сказанного я нашел одно решение, которое заключается в использовании этой библиотеки вместо индикатора выполнения.

Следует отметить, что он говорит вам интегрировать его, добавив:

compile 'me.zhanghai.android.materialprogressbar:library:1.3.0'

Однако, когда я использовал это, это дало мне ошибку из библиотеки поддержки Android для Floating Action Bar. Поэтому я рекомендую вам использовать это вместо этого:

compile 'me.zhanghai.android.materialprogressbar:library:1.1.7'

Пример фрагмента кода о том, как я его использовал:

<me.zhanghai.android.materialprogressbar.MaterialProgressBar
    android:id="@+id/reviewProgressBar"
    style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal"
    android:layout_width="match_parent"
    android:layout_height="6dp"
    android:layout_below="@+id/my_toolbar"
    android:indeterminate="false"
    app:mpb_progressStyle="horizontal"
    app:mpb_useIntrinsicPadding="false"/>

Надеюсь это поможет!

person Charles Li    schedule 18.12.2016

грязный обходной путь, который я использовал, заключался в том, чтобы установить высоту ProgressBar близко к ширине штриха, например:

Индикатор:

<ProgressBar
    android:id="@+id/pb_loading_progress"
    style="@style/Widget.AppCompat.ProgressBar.Horizontal"
    android:layout_width="match_parent"
    android:layout_height="2.1dp"
    android:layout_below="@id/tb_browser"
    android:max="100"
    android:progressDrawable="@drawable/style_browser_progress_drawable"
    android:visibility="invisible" />

Прогресс рисования:

<?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="line">
            <stroke
                android:width="2dp"
                android:color="@color/colorPrimary" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <clip
            android:clipOrientation="horizontal"
            android:gravity="left">
            <shape android:shape="line">
                <stroke
                    android:width="2dp"
                    android:color="@color/white" />
            </shape>
        </clip>
    </item>
</layer-list>

Который выглядел так:

введите здесь описание изображения

person AL.    schedule 01.12.2017
comment
Для меня это хороший ответ. Не нужно обрабатывать сам макет с помощью -paddings или чего-то еще. Когда добавляешь значения в размеры xml, что тогда более понятно. +1 - person Luser_k; 08.06.2018
comment
разве это не работает только для определенного, а не неопределенного? ОП говорит о неопределенном. - person John61590; 09.03.2019
comment
@ John61590 ОП использовал неопределенность в своем вопросе. Но основное внимание было уделено удалению заполнения (отсюда и название), что не должно иметь большого значения, является ли ваш индикатор выполнения определенным или неопределенным. - person AL.; 09.03.2019

Используйте внутри Linearlayout и вы добьетесь успеха простым способом

 <LinearLayout
        android:layout_width="match_parent"
        android:background="#efefef"
        android:layout_height="wrap_content">

        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:visibility="gone"
            android:layout_marginTop="-7dp"
            android:layout_marginBottom="-7dp"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            />

    </LinearLayout>
person alizulfuqar    schedule 05.11.2019

Вы объявили свой вид без какой-либо явной высоты, поэтому его высота выбирается из предопределенного стиля.

<ProgressBar
    android:id="@+id/progressbar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    android:marginTop="-7dp"
    android:visibility="@{loading ? View.VISIBLE : View.GONE}" />

«?android:attr/progressBarStyleHorizontal» будет найден в текущей теме и сохранен в файле attrs.xml. Поскольку это определено платформой, оно получит оттуда значение. На момент написания этого ответа я нахожусь на платформе Android 29, и поиск «? android: attr/progressBarStyleHorizontal» дает следующие результаты.

➜  values 
pwd
/Users/vihaanverma/Library/Android/sdk/platforms/android-29/data/res/values
➜  values 
grep -rin "progressBarStyleHorizontal" . 
./themes_device_defaults.xml:126:        <item name="progressBarStyleHorizontal">@style/Widget.DeviceDefault.ProgressBar.Horizontal</item>
./themes_device_defaults.xml:857:        <item name="progressBarStyleHorizontal">@style/Widget.DeviceDefault.Light.ProgressBar.Horizontal</item>
./themes.xml:272:        <item name="progressBarStyleHorizontal">@style/Widget.ProgressBar.Horizontal</item>
./themes_holo.xml:263:        <item name="progressBarStyleHorizontal">@style/Widget.Holo.ProgressBar.Horizontal</item>
./themes_holo.xml:626:        <item name="progressBarStyleHorizontal">@style/Widget.Holo.Light.ProgressBar.Horizontal</item>
./public.xml:148:  <public type="attr" name="progressBarStyleHorizontal" id="0x01010078" />
./themes_material.xml:258:        <item name="progressBarStyleHorizontal">@style/Widget.Material.ProgressBar.Horizontal</item>
./themes_material.xml:635:        <item name="progressBarStyleHorizontal">@style/Widget.Material.Light.ProgressBar.Horizontal</item>
./styles_material.xml:1010:        <item name="progressBarStyle">?attr/progressBarStyleHorizontal</item>
./attrs.xml:684:        <attr name="progressBarStyleHorizontal" format="reference" />
➜  values 

Открыв один из файлов, содержащих «progressBarStyleHorizontal», вы увидите, что minHeight определен в стиле и равен 16dp.

<style name="Widget.Material.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
    <item name="progressDrawable">@drawable/progress_horizontal_material</item>
    <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material</item>
    <item name="minHeight">16dip</item>
    <item name="maxHeight">16dip</item>
</style>

Это является причиной дополнительной прокладки, которую вы получаете. Вы можете исправить это, указав высоту просмотра и значение scaleY, как показано ниже.

<ProgressBar
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:indeterminate="true"
    android:scaleY="5"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

введите здесь описание изображения

person Vihaan Verma    schedule 05.01.2020