自定义ProgressBar小部件

时间:2010-10-01 16:39:31

标签: iphone android progress-bar

我正在尝试执行与this类似的操作,但在Android中。

alt text

在Android中我可以扩展ProgressBar,但我怀疑如何在顶部添加TextViews。在iPhone中它很容易,因为我可以使用绝对位置,但不是在这里。

有什么想法吗?

编辑: 我决定使用SeekBar代替ProgressBar来添加拇指绘图。我在下面评论过。有些要注意的事项:

  • 我使用的是硬编码值,实际上是三个,但可以更多或更少。
  • 当拇指移动时,它移动到50但它应该移动到不同的选项。
  • 我使用的是像素而不是dpi。我应该解决这个问题。
  • 我需要解决拇指移动时缺少动画的问题。

到目前为止我的进展:

public class SliderFrameLayout extends FrameLayout implements OnSeekBarChangeListener {
    private SeekBar mSlider;
    private Context mContext;
    private int mSize = 3;
    private TextView[] mTextViews;
    private String[] mTexts = {"Nafta", "Gas", "Gasoil"};

    public SliderFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        mContext = context;
        setWillNotDraw(false);
        mTextViews = new TextView[mSize];
        addSlider();
        addTextViews();
    }

    private void addTextViews() {
        for ( int i=0 ; i < mSize ; i++ ) {
            TextView tv;
            tv = new TextView(mContext);
            tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT));
            tv.setText(mTexts[i]);
            mTextViews[i] = tv;
            addView(tv);    
        }
    }

    private void addSlider() {
        FrameLayout fl = new FrameLayout(mContext, null);
        LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
        fl.setLayoutParams(params);
        fl.setPadding(30, 30, 30, 0);


        mSlider = new SeekBar(mContext, null);
        LayoutParams lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
        //lp.setMargins(30, 30, 30, 0);
        //mSlider.setPadding(30, 30, 30, 0);
        mSlider.setLayoutParams(lp);
        //mSlider.setMax(mSize-1);
        mSlider.setThumbOffset(30);
        //mSlider.setProgressDrawable(mContext.getResources().getDrawable(R.drawable.slider_track));
        //mSlider.setThumb(mContext.getResources().getDrawable(R.drawable.slider_thumb));
        mSlider.setOnSeekBarChangeListener(this);
        //addView(mSlider);

        fl.addView(mSlider);
        addView(fl);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        Rect rectf = new Rect();
        mSlider.getLocalVisibleRect(rectf);

    Log.d("WIDTH        :",String.valueOf(rectf.width()));
    Log.d("HEIGHT       :",String.valueOf(rectf.height()));
    Log.d("left         :",String.valueOf(rectf.left));
    Log.d("right        :",String.valueOf(rectf.right));
    Log.d("top          :",String.valueOf(rectf.top));
    Log.d("bottom       :",String.valueOf(rectf.bottom));

        int sliderWidth = mSlider.getWidth();

        int padding = sliderWidth / (mSize-1);

        for ( int i=0 ; i < mSize ; i++ ) {
            TextView tv = mTextViews[i];
            tv.setPadding(i* padding, 0, 0, 0);
        }
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress,
            boolean fromUser) {
        // TODO Auto-generated method stub

    }

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

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        Log.d("SEEK", "value: " + seekBar.getProgress());
        seekBar.setProgress(50);
    }
}

4 个答案:

答案 0 :(得分:8)

您已经覆盖onDraw,为什么不自己绘制文本字符串?而不是通过添加TextViews和搞乱填充的开销,只需使用canvas.drawText在正确的位置物理绘制文本字符串。

您可以使用Paint对象指定文本的样式和颜色:

Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
textPaint.setFakeBoldText(true);
textPaint.setSubpixelText(true);
textPaint.setTextAlign(Align.LEFT);

通过在该Paint对象上使用measureText方法获取精确定位,以查找在画布上绘制时特定字符串的宽度:

textWidth = (int)textPaint.measureText(mTexts[i]);

然后你可以迭代你的文本字符串数组并在正确的位置绘制每个字符串。

@Override 
protected void onDraw(Canvas canvas) {
  int myWidth = getMeasuredWidth()-LEFT_PADDING-RIGHT_PADDING;
  int separation = myWidth / (mSize-1);

  for (int i = 0; i++; i < mSize) {
    int textWidth = (int)textPaint.measureText(mTexts[i]);
    canvas.drawText(mTexts[i], 
                    LEFT_PADDING+(i*separation)-(int)(textWidth/2), 
                    TOP_PADDING, 
                    textPaint);
  }
}

你可能想要在onMeasure而不是onDraw上进行测量,你可能只应该在更改文本或绘画时测量每个字符串的宽度,但我把它全部放在一个地方(希望更容易理解。

答案 1 :(得分:1)

试一试。您可以将自定义progressBar放在FrameLayout内,然后在此布局中,您必须添加三个TextViews作为宽度fill_parent。 然后你可以用这种方式对齐三个文本:左,中和右。您的文字不应该覆盖,您可以使用边距调整一点位置。

答案 2 :(得分:0)

您可以使用this ...不完全符合您的要求......但是很容易设置和自定义......

答案 3 :(得分:0)

您可以将TextView设置为:

android:layout_width="0dp"
android:layout_weight="1"

这将让android框架负责TextViews的放置,并避免手动计算每个文本的填充。