【问题标题】:Android - Seekbar with text followingAndroid - 带有文本的搜索栏
【发布时间】:2016-08-02 11:52:18
【问题描述】:

我想创建一个带有以下文本的自定义 SeekBar,该文本会根据拇指的位置更新其位置(和进度)。

我需要达到什么目标:

假设:

  1. 最小值 = 1000
  2. 最大值 = 30000

案例 1: 进度为 0%(或最小值 = 1000),文本应与拇指左边框对齐。

案例 2: 进度文本显示在 Thumb drawable 上方并居中,因为它有空间来绘制自己。

案例 3: 进度为 100%(或最大值 = 3000),文本应与 Thumb 的右边框对齐。

我已经拥有了什么:

public class CustomSeekBar extends SeekBar {
    private Paint paint;
    private int[] coordCenterTemp = new int[]{0, 0};

    // .....

private void init() {
    paint = new Paint();
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setTextSize(sp2px(20));
    paint.setTextAlign(Paint.Align.CENTER);
}

private int sp2px(int sp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}

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

    String str = String.valueOf(getProgress());

    int thumb_x = (int) (( (double)this.getProgress()/this.getMax() ) * (double)(this.getWidth()));
    int thumb_y = 30;

    int textMeasure = (int) paint.measureText(str, 0, str.length());

    if ((textMeasure / 2) + thumb_x <= getRight()) {
        coordCenterTemp[0] = thumb_x;
        coordCenterTemp[1] = thumb_y;
    }
    canvas.drawText(str, coordCenterTemp[0], coordCenterTemp[1], paint);
}
}

这适用于进度为 50% 时。一旦我向右或向左滑动,文本就会被绘制到错误的方向。

我怎样才能做到这一点?

【问题讨论】:

    标签: android textview android-canvas draw android-seekbar


    【解决方案1】:

    我最近实现了这样一个功能,这是我的代码:

    首先定义一个 ThumbTextView,它位于您的TextView 上方的Seekbar

    public class ThumbTextView extends TextView {
    
        private LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        private int width = 0;
    
        public ThumbTextView(Context context) {
            super(context);
        }
    
        public ThumbTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public void attachToSeekBar(SeekBar seekBar) {
            String content = getText().toString();
            if (TextUtils.isEmpty(content) || seekBar == null)
                return;
            float contentWidth = this.getPaint().measureText(content);
            int realWidth = width - seekBar.getPaddingLeft() - seekBar.getPaddingRight();
            int maxLimit = (int) (width - contentWidth - seekBar.getPaddingRight());
            int minLimit = seekBar.getPaddingLeft();
            float percent = (float) (1.0 * seekBar.getProgress() / seekBar.getMax());
            int left = minLimit + (int) (realWidth * percent - contentWidth / 2.0);
            left = left <= minLimit ? minLimit : left >= maxLimit ? maxLimit : left;
            lp.setMargins(left, 0, 0, 0);
            setLayoutParams(lp);
    
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if (width == 0)
                width = MeasureSpec.getSize(widthMeasureSpec);
        }
    }
    

    然后定义您自己的 ThumbTextSeekBar 类,它是 SeekbarThumbSeekbar 的包装器:

    public class ThumbTextSeekBar extends LinearLayout {
    
        public ThumbTextView tvThumb;
        public SeekBar seekBar;
        private SeekBar.OnSeekBarChangeListener onSeekBarChangeListener;
    
        public ThumbTextSeekBar(Context context) {
            super(context);
            init();
        }
    
        public ThumbTextSeekBar(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            LayoutInflater.from(getContext()).inflate(R.layout.view_thumb_text_seekbar, this);
            setOrientation(LinearLayout.VERTICAL);
            tvThumb = (ThumbTextView) findViewById(R.id.tvThumb);
            seekBar = (SeekBar) findViewById(R.id.sbProgress);
            seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                    if (onSeekBarChangeListener != null)
                        onSeekBarChangeListener.onStopTrackingTouch(seekBar);
                }
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                    if (onSeekBarChangeListener != null)
                        onSeekBarChangeListener.onStartTrackingTouch(seekBar);
                }
    
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    if (onSeekBarChangeListener != null)
                        onSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
                    tvThumb.attachToSeekBar(seekBar);
                }
            });
    
        }
    
        public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l) {
            this.onSeekBarChangeListener = l;
        }
    
        public void setThumbText(String text) {
            tvThumb.setText(text);
        }
    
        public void setProgress(int progress) {
            if (progress == seekBar.getProgress() && progress == 0) {
                seekBar.setProgress(1);
                seekBar.setProgress(0);
            } else {
                seekBar.setProgress(progress);
            }
        }
    }
    

    最后,以如下方式使用它:

    thumbTextSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                
                    thumbTextSeekbar.setThumbText(seekBar.getProgress()));
    
                }
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                    thumbTextSeekbar.showTxt();
                }
    
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                    thumbTextSeekbar.hideTxt();
                }
            });
    

    为了确保一切都完整,这里是R.layout.view_thumb_text_seekbar

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    
        <xxx.ui.widget.ThumbTextView
            android:id="@+id/tvThumb"
            style="@style/Textview.White.MediumSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/round_rect_black_trans"
            android:padding="4dp"
            android:visibility="gone" />
    
        <SeekBar
            android:id="@+id/sbProgress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="-16dp"
            android:layout_marginRight="-16dp"
            android:layout_marginTop="5dp"
            android:minHeight="20dp" />
    
    </merge>
    

    输出:

    【讨论】:

    • 它需要一些调整,但这是一个很好的例子!谢谢!
    • 您能否在答案中添加 R.layout.view_thumb_text_seekbar 以及 xml 实现
    • @Janku 添加 :)
    • 能否请您在放置此搜索栏的位置添加设计 xml 以及活动 java 代码
    • 实际上我想要做的是,当我将搜索栏的进度设置为 16 时,默认情况下拇指会根据进度编号在顶部而不滚动搜索栏
    猜你喜欢
    • 1970-01-01
    • 2016-01-04
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    相关资源
    最近更新 更多