具有动态文本的自定义拇指的Android SeekBar

9
我希望创建一个自定义的 Android SeekBar,其中拇指内含文本以显示当前查找位置。
这是我的代码:
SeekBar sb;

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.custom_seek_bar_activity);

    sb = (SeekBar)findViewById(R.id.slider);
    sb.setMax(100);
    sb.setProgress(10);
    BitmapDrawable bd = writeOnDrawable(R.drawable.star2, Double.toString(50));

    sb.setThumb(bd);

    sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
        {
            int pos = sb.getProgress();
            double star = pos/(20.0);
            TextView tv = (TextView)findViewById(R.id.percent);
            tv.setText(Double.toString(star)+"%");
            BitmapDrawable bd = writeOnDrawable(R.drawable.star2, Double.toString(star));
            bd.setBounds(new Rect(0,0, 
                bd.getIntrinsicWidth(), 
                bd.getIntrinsicHeight()
            ));
            seekBar.setThumb(bd);
        }

        @Override
        public void onStartTrackingTouch(SeekBar arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onStopTrackingTouch(SeekBar arg0) {
            // TODO Auto-generated method stub

        }
    });

}   

public BitmapDrawable writeOnDrawable(int drawableId, String text){

    Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId).copy(Bitmap.Config.ARGB_8888, true);

    Paint paint = new Paint(); 
    paint.setStyle(Style.FILL);  
    paint.setColor(Color.BLACK); 
    paint.setTextSize(10); 

    Canvas canvas = new Canvas(bm);
    canvas.drawText(text, 0, bm.getHeight()/2, paint);

    return new BitmapDrawable(bm);
}

但是当我移动滑块时,它会回到进度条的开头。有没有人知道如何将自定义滑块与进度条位置一起移动?
4个回答

15

我在我的应用程序中使用SeekBar来显示计时器倒计时。我使用以下代码在定时器拇指内显示当前SeekBar进度数:

    SeekBar timerBar = (SeekBar) findViewById(R.id.seekBarTimer);
    if (timerBar != null) {
        timerBar.setMax((int) (Settings.countdownSeconds + 1));
        timerBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

            @Override
            public void onStopTrackingTouch(SeekBar arg0) {
            }

            @Override
            public void onStartTrackingTouch(SeekBar arg0) {
            }

            @Override
            public void onProgressChanged(SeekBar timerBar, int arg1, boolean arg2) {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.seek_thumb);
                Bitmap bmp = bitmap.copy(Bitmap.Config.ARGB_8888, true);
                Canvas c = new Canvas(bmp);
                String text = Integer.toString(timerBar.getProgress());
                Paint p = new Paint();
                p.setTypeface(Typeface.DEFAULT_BOLD);
                p.setTextSize(14);
                p.setColor(0xFFFFFFFF);
                int width = (int) p.measureText(text);
                int yPos = (int) ((c.getHeight() / 2) - ((p.descent() + p.ascent()) / 2));
                c.drawText(text, (bmp.getWidth()-width)/2, yPos, p);
                timerBar.setThumb(new BitmapDrawable(getResources(), bmp));
            }
        });
        timerBar.setProgress(0);
    }

R.drawable.seek_thumb是我的滑块 drawable。


4
我现在得到了解决方案,在setBound()方法中,我将左上角传递为0,这就是为什么它显示在开头的拖动条。在进行以下更改后,我使其工作。

onProgressChanged()事件中调用setThumbPos()方法。

public void setThumbPosition(SeekBar seekBar){
    int max = seekBar.getMax();

    int available = seekBar.getWidth() - seekBar.getPaddingLeft() - seekBar.getPaddingRight();
    float scale = max > 0 ? (float) seekBar.getProgress() / (float) max : 0;

    //scale = 1;
    int pos = sb.getProgress();
    double star = pos/(20.0);

    BitmapDrawable bd = writeOnDrawable(R.drawable.star2, Double.toString(star));

    int thumbWidth = bd.getIntrinsicWidth();
    int thumbHeight = bd.getIntrinsicHeight();
    //available -= thumbWidth;

    int thumbPos = (int) (scale * available);
    if(thumbPos <= 0+thumbWidth){
        thumbPos += (thumbWidth/2);
    }else if(thumbPos >= seekBar.getWidth()-thumbWidth){
        thumbPos -= (thumbWidth/2);
    }

    bd.setBounds(new Rect(thumbPos,0, 
            thumbPos+bd.getIntrinsicWidth(), 
        bd.getIntrinsicHeight()
    ));

    seekBar.setThumb(bd);

    TextView tv = (TextView)findViewById(R.id.percent);
    tv.setText(Double.toString(star)+"%");
}

2
我最终采用了这个简单的解决方案。虽然它可能没有一个真正定制的SeekBar那么高效,但是它非常容易插入到现有的布局中,并且可以在SeekBar拇指上方使用任何标签或其他视图。
protected void positionThumbLabel(SeekBar seekBar, TextView label)
{
  Rect tr = seekBar.getThumb().getBounds();
  label.setWidth(tr.width());
  label.setX(tr.left + seekBar.getPaddingLeft());
}

通过一些小的改变,您可以将覆盖层相对于滑块中心定位:

protected void positionThumbOverlayCenter(SeekBar seekBar, View overlay)
{
  Rect tr = seekBar.getThumb().getBounds();
  overlay.setX(tr.centerX() - (overlay.getWidth() * 0.5f) + seekBar.getPaddingLeft());
}

-1

1
链接已失效。你能提供一个替代方案吗? - kilokahn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接