2012-05-10 8 views
10

Tengo un problema para establecer programáticamente el dibujo de progreso de una SeekBar. Cuando lo configuro en el archivo .xml, todo funciona bien.Cómo establecer el progreso de Android SeekBar dibujable programáticamente

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

set from .xml

Pero, tengo un problema cuando intento configurarlo de código como este:

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

Antecedentes dibujable continuación, toma la totalidad barra de búsqueda, y no estoy capaz de modificar el progreso en cualquier momento más adelante - el pulgar se mueve pero el dibujo progresivo todavía llena toda la barra de búsqueda. Además, la barra de búsqueda pierde sus esquinas redondeadas. Parece que el progreso dibujable está en la parte superior de la barra de búsqueda.

when set in code

Probé la solución aportada en android progressBar does not update progress view/drawable, pero no funciona para mí.

ayuda apreciada,

Milos

Respuesta

22

He resuelto el problema mediante el uso de la forma .xml como fondo para mi SeekBar. La solución SeekBar completa que se puede utilizar a través de setProgressDrawable() método debe ser como este:

//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> 

En el código, se puede utilizar de esta manera:

progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.seek_bar)); 
+0

¡Gran solución! – jbc25

6

He tenido problemas cambiando buscar y barras de progreso de código antes. Una vez tuve que cargar el dibujo dos veces antes de que entrara en vigor correctamente. Creo que estaba relacionado con el relleno después de cambiar la imagen.

sólo estoy adivinando, pero intente establecer el relleno después con

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

y no hace daño a invalidarla.

seekBar.postInvalidate() 

poco limpia y no me gusta, pero es resuelto algo similar para mí antes

+1

Acabo de probarlo, y no resuelve el problema :( –

9

La respuesta anterior es para usando xml, pero por si alguien quisiera hacer esto programáticamente lo tengo a continuación.

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; 
} 

}

Por encima de clase es para el fondo de la barra de búsqueda (la parte que siempre existe bajo el dibujable progreso)

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; 
} 

}

Arriba está el dibujable progreso. Tenga en cuenta que es un clip dibujable. Lo bueno de esto es que estoy estableciendo los límites para ser lo que quiera, junto con el color. Esto permite una personalización ajustada de su dibujo.

//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); 

El código anterior utiliza plantillas personalizables para editar la barra de búsqueda. Mi principal razón para hacer esto es que voy a editar el aspecto del fondo dibujable, por lo que tiene "muescas" (aunque aún no se ha implementado). No puede hacer eso con un xml definido dibujable (al menos no fácil).

Otra cosa que noté es que este proceso evita que el SeekBar sea tan ancho como el del pulgar dibujable. Establece los límites de los drawables para que nunca lleguen a ser altos.

+0

He probado su solución, pero ¿puede ajustarla para que las esquinas se redondeen? Aún más complicada es que necesita redondearse a la izquierda, pero no a la derecha (a menos que sea una barra de progreso completa), aunque no sé cómo funciona realmente. – user1122069

+0

Si te estás refiriendo al fondo dibujable, sí puedes. en lugar de canvas.drawRect dentro de SeeBarBackgroundDrawable.draw(), use canvas.drawRoundRect para dibujar el lado izquierdo. Luego, haga otro canvas.drawRect para dibujar el lado derecho que se solapa con el lado derecho redondeado de la ronda Rect. Esto le dará un rectángulo con bordes redondeados en el lado izquierdo, y bordes afilados en el lado derecho. – Danuofr

Cuestiones relacionadas