web-dev-qa-db-ja.com

プログラムで描画可能なSeekBarの進行状況を設定する方法Android

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

その後、背景ドローアブルはシークバー全体を取得します。後で進行状況を変更することはできません。親指は移動しますが、進行状況ドローアブルはシークバー全体を埋めます。また、シークバーは丸みを帯びた角を失います。プログレスドローアブルはシークバーの上にあるようです。

when set in code

AndroidのprogressBarは進行状況の表示/描画可能を更新しません で提供されているソリューションを試しましたが、機能しません。

12
Milos Pesic

SeekBarの背景として.xmlシェイプを使用することで、問題を解決しました。 setProgressDrawable()メソッドを介して使用できる完全なSeekBarソリューションは、次のようになります。

//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));
23
Milos Pesic

上記の答えは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で定義されたドローアブルではそれを行うことはできません(少なくとも簡単ではありません)。

私が気付いたもう1つのことは、このプロセスにより、SeekBarが親指で描画できる幅になるのを防ぐことです。ドローアブルの境界を設定して、ドローアブルが高くならないようにします。

9
Danuofr

以前、コードからシークバーとプログレスバーを変更する際に問題が発生しました。一度、ドローアブルが正しく有効になる前に、実際に2回ロードする必要がありました。画像変更後のパディングに関係していると思います。

ここで推測しているだけですが、後でパディングを設定してみてください

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

また、それを無効にすることを傷つけることはできませんでした。

 seekBar.postInvalidate()

非常にハッキーで、私はそれが好きではありませんが、以前は私にとって同様の問題を解決しました

6
Jason

xMLでAndroid:maxHeightを使用して、背景の高さを制限できます

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

そしてそれは親指をクリップしません

0
xiao xinpeng