Ответ 1
В качестве обходного пути для этой проблемы я использую следующее.
android:layout_marginBottom="-8dp"
android:layout_marginTop="-4dp"
По умолчанию ProgressBar имеет определенное дополнение над и под панелью. Есть ли способ удалить это дополнение, чтобы в конце концов иметь только панель?
В качестве обходного пути для этой проблемы я использую следующее.
android:layout_marginBottom="-8dp"
android:layout_marginTop="-4dp"
Вот как я использовал Juozas:
высота моего ProgressBar
равна 4dp. Поэтому я создал FrameLayout
с высотой 4dp и установил layout_gravity
от ProgressBar
до center
. Он работает как шарм.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="4dp">
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="center"
android:indeterminate="true"/>
</FrameLayout>
Я решил использовать специальную библиотеку для решения этой проблемы. Большинство других решений работают, но результаты не согласуются между различными устройствами.
MaterialProgressBar
- Совлокальный внешний вид на Android 4.0 +.
- Корректировка цвета между платформами.
- Возможность удалить внутреннее дополнение рамки ProgressBar.
- Возможность скрывать трассу рамки горизонтального ProgressBar.
- Используется как замена для рамки ProgressBar.
Чтобы добавить как зависимость gradle:
compile 'me.zhanghai.android.materialprogressbar:library:1.1.7'
Чтобы добавить ProgressBar без встроенного дополнения к вашему макету:
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:layout_width="wrap_content"
android:layout_height="4dp"
android:indeterminate="true"
app:mpb_progressStyle="horizontal"
app:mpb_useIntrinsicPadding="false"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal" />
app:mpb_useIntrinsicPadding="false"
делает трюк. Подробнее см. на странице GitHub.
Можно создать вертикально центрированный ProgressBar внутри родителя, который будет отжимать отступ. Поскольку ProgressBar не может сделать себя более крупным, чем родительский, мы должны создать большой родительский объект для размещения внутри обрезающего представления.
<FrameLayout
android:id="@+id/clippedProgressBar"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="4dp"
tools:ignore="UselessParent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_gravity="center_vertical">
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:indeterminate="true"/>
</FrameLayout>
</FrameLayout>
Полное решение этой проблемы было бы следующим. На всякий случай, если кому-то нужны фрагменты кода, это то, что я сделал.
Здесь находится progress_indeterminate_horizontal_holo.xml
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/progressbar_indeterminate_holo1" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo2" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo3" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo4" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo5" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo6" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo7" android:duration="50" />
<item android:drawable="@drawable/progressbar_indeterminate_holo8" android:duration="50" />
Ресурсы стиля скопированы в мой файл локальных стилей.
<style name="Widget">
<item name="android:textAppearance">@android:attr/textAppearance</item>
</style>
<style name="Widget.ProgressBar">
<item name="android:indeterminateOnly">true</item>
<item name="android:indeterminateBehavior">repeat</item>
<item name="android:indeterminateDuration">3500</item>
</style>
<style name="Widget.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item>
<item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_holo</item>
</style>
И, наконец, установите минимальную высоту в 4dp в моем локальном файле макета.
<ProgressBar
android:id="@+id/pb_loading"
style="@style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:indeterminate="true"
android:minHeight="4dp"
android:minWidth="48dp"
android:progressDrawable="@drawable/progress_indeterminate_horizontal_holo" />
Если кому-то все еще нужна помощь, можете попробовать это:
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline" android:indeterminate="true"
android:visibility="visible" app:layout_constraintBottom_toTopOf="@+id/guideline"/>
Здесь индикатор выполнения находится внутри ConstraintLayout, а атрибуты constraintTop_toTopOf и constraintBottom_toTopOf должны применяться к одному и тому же элементу (в данном случае это указание).
Ответ Subin, кажется, единственный (в настоящее время), который не является хрупким взломом, подверженным поломке в будущих версиях Android ProgressBar.
Но вместо того, чтобы разбираться с ресурсами, изменять их и поддерживать их в течение неопределенного времени, я решил использовать библиотеку MaterialProgressBar, которая делает это для нас:
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_gravity="bottom"
custom:mpb_progressStyle="horizontal"
custom:mpb_showTrack="false"
custom:mpb_useIntrinsicPadding="false"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
/>
В build.gradle:
// Android horizontal ProgressBar doesn't allow removal of top/bottom padding
compile 'me.zhanghai.android.materialprogressbar:library:1.1.6'
У этого проекта есть хорошая демонстрация, которая показывает различия между ним и встроенным ProgressBar.
Я встретил ту же проблему при использовании progressbar с горизонтальным стилем.
Основная причина заключается в том, что 9-патч по умолчанию для строки выполнения: (progress_bg_holo_dark.9.png) имеет несколько вертикальных прозрачных пикселей в качестве отступов.
Окончательное решение, которое сработало для меня: настройте достигнутый прогресс, мой пример кода:
custom_horizontal_progressbar_drawable.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 android:shape="rectangle">
<solid android:color="#33ffffff" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape android:shape="rectangle">
<solid android:color="#ff9800" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape android:shape="rectangle">
<solid android:color="#E91E63" />
</shape>
</clip>
</item>
</layer-list>
макет фрагмента:
<ProgressBar
android:id="@+id/song_progress_normal"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_alignParentBottom="true"
android:progressDrawable="@drawable/custom_horizontal_progressbar_drawable"
android:progress="0"/>
Одна хитрость заключается в добавлении отрицательных полей в ваш индикатор выполнения.
Ниже приведен пример кода XML, предполагая его в верхней части экрана:
<ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-7dp"
android:layout_marginBottom="-7dp"
android:indeterminate="true" />
Я использую minHeight и maxHeigh. Это помогает для разных версий Api.
<ProgressBar
android:id="@+id/progress_bar"
style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="3dp"
android:minHeight="3dp" />
Он должен использовать оба. Api 23 работает хорошо с
android:layout_height="wrap_content"
android:minHeight="0dp"
Но более низкие версии Api в этом случае увеличивают высоту шага выполнения до maxHeight.
Чтобы удалить вертикальное заполнение ProgressBar
, вы можете сделать:
ProgressBar
Пример содержит 1 wrap_content ProgressBar
, 1 8dp ProgressBar
, 1 100dp ProgressBar
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
...
android:layout_height="8dp"
android:scaleY="2" />
добавление android: progressDrawable в список слоев, определенный в drawable, исправил проблему для меня. Он работает, маскируя панель progess в пользовательских возможностях
пример реализации описан в fooobar.com/questions/52705/...
Я использую style="@style/Widget.AppCompat.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>
Я просто перевернул минимальную/максимальную высоту:
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="2dp"
android:indeterminate="true"
android:minHeight="2dp"
android:maxHeight="2dp" />
Попробуйте следующее:
<ProgressBar
android:id="@+id/progress_bar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:progress="25"
android:progressTint="@color/colorWhite"
android:progressBackgroundTint="@color/colorPrimaryLight"
android:layout_width="match_parent"
android:layout_height="4dp" />
... и затем настройте индикатор выполнения для ваших нужд, так как вначале отобразится панель среднего размера с желтым цветом с оттенком серого цвета. Также обратите внимание, что нет вертикальной прокладки.
<ProgressBar
android:layout_marginTop="-8dp"
android:layout_marginLeft="-8dp"
android:layout_marginRight="-8dp"
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="4dp"
android:indeterminate="false"
android:indeterminateTint="@color/white"
android:max="100"
android:paddingStart="8dp"
android:paddingRight="0dp"
android:progressDrawable="@drawable/progress_bg" />
Нет необходимости загружать какой-либо новый модуль или даже размещать FrameLayout вокруг вашего индикатора выполнения. Это все просто хаки. Всего 2 шага:
В вашем what.xml
<ProgressBar
android:id="@+id/workoutSessionGlobalProgress"
android:layout_width="match_parent"
android:layout_height="YOUR_HEIGHT"
android:progressDrawable="@drawable/progress_horizontal"
android:progress="0"
<!-- High value to make ValueAnimator smoother -->
android:max="DURATION * 1000"
android:indeterminate="false"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal"/>
progress_horizont.xml, измените значения, как вам угодно.
Не любите закругленные углы?
Удалить радиус угла
Не любите цвета? Изменить цвета и т.д. Готово!
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ff9d9e9d"
android:centerColor="#ff5a5d5a"
android:centerY="0.75"
android:endColor="#ff747674"
android:angle="270"
/>
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#80ffd300"
android:centerColor="#80ffb600"
android:centerY="0.75"
android:endColor="#a0ffcb00"
android:angle="270"
/>
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ffffd300"
android:centerColor="#ffffb600"
android:centerY="0.75"
android:endColor="#ffffcb00"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>
Как правило, это шаги для изменения кода того, что вам не нравится. Просто найдите исходный код и выясните, что нужно изменить. Если вы будете следовать исходному коду ProgressBar, вы найдете файл с именем progress_horizont.xml, на который он ссылается. В основном, как я решаю все свои проблемы с XML.
Лучшее решение должно быть
android:minHeight="0dp"
Нет обходного пути и работает как шарм.
Простое решение без трюков, совместимое с любой версией Android и не нуждающееся в внешних библиотеках, фальсифицирует ProgressBar
двумя Views
внутри LinearLayout
. Это то, чем я закончил. Выглядит довольно аккуратно, и этот подход довольно гибкий - вы можете оживить его с помощью фанковых способов, добавить текст и т.д.
Разметка:
<LinearLayout
android:id="@+id/inventory_progress_layout"
android:layout_width="match_parent"
android:layout_height="4dp"
android:orientation="horizontal">
<TextView
android:id="@+id/inventory_progress_value"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/inventory_progress_remaining"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
код:
public void setProgressValue(float percentage) {
TextView progressValue = (TextView) findViewById(R.id.inventory_progress_value);
TextView progressRemaining = (TextView) findViewById(R.id.inventory_progress_remaining);
LinearLayout.LayoutParams paramsValue = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
LinearLayout.LayoutParams paramsRemaining = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
paramsValue.weight = (100 - percentage);
paramsRemaining.weight = percentage;
progressValue.setLayoutParams(paramsValue);
progressRemaining.setLayoutParams(paramsRemaining);
}
Результат (с добавлением некоторой отметки):