How to set Android SeekBar progress drawable programmatically
I solved the problem by using .xml shape as background for my SeekBar. The complete SeekBar solution that can be used via setProgressDrawable() method should be like this:
//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>
In the code, you can use it like this:
progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar));
The answer given above is for using xml, but just in case someone wanted to do this programmatically I have it below.
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;
}
}
Above class is for the background of the seekbar (the part that always exists under the progress drawable)
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;
}
}
Above is the progress drawable. Notice it's a clip drawable. The cool part here is I am setting the bounds to be whatever I want, along with color. This allows for fine tuned customization of your drawable.
//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);
Above code uses custom drawables to edit seek bar. My main reason for doing this is I will be editing the look of the background drawable, so it has "notches" (although not implemented yet). You can't do that with a xml defined drawable (at-least not easily).
Another thing I noticed is that this process prevents the SeekBar's from getting as wide as the thumb drawable. It sets the bounds of the drawables so they never get to tall.