Как настроить прогресс прорисовки 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"/>

и он не будет зажимать большой палец