Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set Android SeekBar progress drawable programmatically

I have a problem with programmatically setting the progress drawable of a SeekBar. When I set it in the .xml file everything is working fine.

<SeekBar
 android:id="@+id/sb"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 .....
 android:progressDrawable="@drawable/seek_bar"/>

set from .xml

But, I have a problem when I try to set it from code like this:

seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar));

Background drawable then takes the whole seek bar, and I'm not able to modify the progress at all later on - the thumb moves but the progress drawable still fills whole seekbar. Also, seekbar looses its rounded corners. It seems that progress drawable is on top of the seekbar.

when set in code

I tried the solution provided on android progressBar does not update progress view/drawable, but it doesn't work for me.

like image 996
Milos Pesic Avatar asked May 10 '12 14:05

Milos Pesic


People also ask

How to set SeekBar progress value in Android?

The user can touch the thumb and drag left or right to set the current progress level or use the arrow keys. Placing focusable widgets to the left or right of a SeekBar is discouraged.

How to implement SeekBar in Android?

Step1: Create a new project. After that, you will have java and XML file. Step2: Open your xml file and add a SeekBar and TextView for message as shown below, max attribute in SeekBar define the maximum it can take. Assign ID to SeekBar And TextView.

How can I increase my SeekBar size?

You can do this via XML. It will work fine in your application.do this simple integration in your XML where you have mentioned the Progress Bar tag. Edit the maxHeight to your desired height what you want to achieve. It will work perfectly.

How to get value from SeekBar Android?

The SeekBar class is a subclass of ProgressBar , which contains a getProgress() method. Calling PRICEbar. getProgress() will return the value you are looking for.


4 Answers

you can use android: maxHeight in you XML, to limit background height

<SeekBar
    android:id="@+id/original_volume"
    android:layout_width="120dp"
    android:layout_height="wrap_content"
    android:maxHeight="2dp"/>

and it will not clip the thumb

like image 103
xiao xinpeng Avatar answered Oct 28 '22 01:10

xiao xinpeng


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));
like image 27
Milos Pesic Avatar answered Oct 28 '22 01:10

Milos Pesic


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.

like image 41
Danuofr Avatar answered Oct 28 '22 00:10

Danuofr


I've had issues changing seek and progress bars from code before. Once I actually had to load the drawable twice before it took effect properly. I think it was related to padding after changing the image.

I'm just guessing here, but try setting the padding afterwards with

 getResources().getDrawable(R.drawable.seek_bar) // once
 seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar)); //twice
 seekBar.setPadding(int,int,int,int)

and also couldn't hurt to invalidate it.

 seekBar.postInvalidate()

Very hacky and I dont like it, but it solved something similar for me before

like image 42
Jason Avatar answered Oct 28 '22 00:10

Jason