Как настроить прогресс прорисовки Android SeekBar программно
У меня проблема с программной настройкой прорисовки прогресса SeekBar. Когда я устанавливаю его в XML файл, все работает нормально.
<SeekBar
android:id="@+id/sb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
.....
android:progressDrawable="@drawable/seek_bar"/>
![set from .xml]()
Но у меня есть проблема, когда я пытаюсь установить его из кода следующим образом:
seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar));
Затем фон для рисования занимает всю полосу поиска, и я не могу изменить ход выполнения позже - большой палец перемещается, но рисующий прогресс все еще заполняет всю панель поиска. Кроме того, seekbar теряет свои закругленные углы. Кажется, что прогресс рисования находится на верхней части панели поиска.
![when set in code]()
Я попробовал решение, представленное на Android ProgressBar, не обновляет прогресс просмотра/рисования, но он не работает для меня.
Ответы
Ответ 1
Я решил проблему, используя форму .xml в качестве фона для моего SeekBar.
Полное решение SeekBar, которое может быть использовано с помощью метода setProgressDrawable(), должно быть таким:
//seek_bar.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"
android:drawable="@drawable/seek_bar_background"/>
<item android:id="@android:id/progress"
android:drawable="@drawable/seek_bar_progress" />
</layer-list>
//seek_bar_background.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<gradient
android:angle="270"
android:startColor="#8a8c8f"
android:endColor="#58595b" />
<corners android:radius="5dip" />
</shape>
//seek_bar_progress.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"
android:drawable="@drawable/seek_bar_background"/>
<item android:id="@android:id/progress">
<clip android:drawable="@drawable/seek_bar_progress_fill" />
</item>
</layer-list>
//seek_bar_progress_fill.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<gradient
android:startColor="#b3d27e"
android:endColor="#93c044"
android:angle="270"
/>
<corners android:radius="5dip" />
</shape>
В коде вы можете использовать его следующим образом:
progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar));
Ответ 2
Ответ, приведенный выше, предназначен для использования xml, но на всякий случай кто-то захотел сделать это программно, я его ниже.
public class SeekBarBackgroundDrawable extends Drawable {
private Paint mPaint = new Paint();
private float dy;
public SeekBarBackgroundDrawable(Context ctx) {
mPaint.setColor(Color.WHITE);
dy = ctx.getResources().getDimension(R.dimen.one_dp);
}
@Override
public void draw(Canvas canvas) {
canvas.drawRect(getBounds().left,getBounds().centerY()-dy/2,getBounds().right,getBounds().centerY()+dy/2,mPaint);
}
@Override
public void setAlpha(int i) {
mPaint.setAlpha(i);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Над классом находится фон поиска (часть, которая всегда существует при достижении прогресса)
public class SeekBarProgressDrawable extends ClipDrawable {
private Paint mPaint = new Paint();
private float dy;
private Rect mRect;
public SeekBarProgressDrawable(Drawable drawable, int gravity, int orientation, Context ctx) {
super(drawable, gravity, orientation);
mPaint.setColor(Color.WHITE);
dy = ctx.getResources().getDimension(R.dimen.two_dp);
}
@Override
public void draw(Canvas canvas) {
if (mRect==null) {
mRect = new Rect(getBounds().left, (int)(getBounds().centerY() - dy / 2), getBounds().right, (int)(getBounds().centerY() + dy / 2));
setBounds(mRect);
}
super.draw(canvas);
}
@Override
public void setAlpha(int i) {
mPaint.setAlpha(i);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Выше - прогресс, доступный. Обратите внимание на то, что клип доступен. Крутая часть здесь - я устанавливаю границы как все, что захочу, и цвет. Это позволяет точно настроить настроечные настройки.
//Custom background drawable allows you to draw how you want it to look if needed
SeekBarBackgroundDrawable backgroundDrawable = new SeekBarBackgroundDrawable(mContext);
ColorDrawable progressDrawable = new ColorDrawable(Color.BLUE);
//Custom seek bar progress drawable. Also allows you to modify appearance.
SeekBarProgressDrawable clipProgressDrawable = new SeekBarProgressDrawable(progressDrawable,Gravity.LEFT,ClipDrawable.HORIZONTAL,mContext);
Drawable[] drawables = new Drawable[]{backgroundDrawable,clipProgressDrawable};
//Create layer drawables with android pre-defined ids
LayerDrawable layerDrawable = new LayerDrawable(drawables);
layerDrawable.setId(0,android.R.id.background);
layerDrawable.setId(1,android.R.id.progress);
//Set to seek bar
seekBar.setProgressDrawable(layerDrawable);
Выше кода использует пользовательские чертежи для редактирования строки поиска. Моя основная причина для этого заключается в том, что я буду редактировать внешний вид фона, поэтому он имеет "вырезы" (хотя еще не реализованы). Вы не можете сделать это с помощью xml, определяемого drawable (по крайней мере, не так легко).
Еще одна вещь, которую я заметил, заключается в том, что этот процесс не позволяет SeekBar получить ширину, как большой палец. Он устанавливает границы чертежей, чтобы они никогда не становились высокими.
Ответ 3
У меня были проблемы с изменением баров поиска и прогресса из кода раньше. Как только мне на самом деле пришлось загрузить растягиваемое дважды, прежде чем оно вступило в силу правильно. Я думаю, что это связано с заполнением после изменения изображения.
Я просто угадываюсь здесь, но попробую установить дополнение после
getResources().getDrawable(R.drawable.seek_bar) // once
seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar)); //twice
seekBar.setPadding(int,int,int,int)
а также не может навредить его недействительности.
seekBar.postInvalidate()
Очень хаки, и мне это не нравится, но он решил что-то подобное для меня раньше
Ответ 4
Вы можете использовать Android: maxHeight в вашем XML, чтобы ограничить высоту фона
<SeekBar
android:id="@+id/original_volume"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:maxHeight="2dp"/>
и он не будет зажимать большой палец