Android – панель поиска с последующим текстом

Я хочу создать собственный SeekBar со следующим текстом, который обновляет свою позицию (и прогресс) в зависимости от того, где находится большой палец.

Что мне нужно сделать:

Поиск с последующим текстом

Предположения:

  1. Минимальное значение = 1000
  2. Максимальное значение = 30000

Случай 1. Ход выполнения составляет 0 % (или минимальное значение = 1000), а текст должен быть выровнен по левой границе бегунка.

Случай 2: текст выполнения отображается над возможностью рисования Thumb и центрируется, так как у него есть место для рисования.

Вариант 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%. Как только я двигаюсь вправо или влево, текст рисуется с некоторым смещением в неправильном направлении.

Как я могу это сделать?


person Bugdr0id    schedule 02.08.2016    source источник


Ответы (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, который является оболочкой для Seekbar и ThumbSeekbar:

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>

Выход:

введите здесь описание изображения

person Amir    schedule 02.08.2016
comment
это требует некоторых настроек, но это отличный пример того, как это сделать! Спасибо! - person Bugdr0id; 02.08.2016
comment
не могли бы вы добавить R.layout.view_thumb_text_seekbar с ответом, а также реализацию xml - person Janku; 08.06.2018
comment
@Janku добавил :) - person Amir; 08.06.2018
comment
не могли бы вы добавить дизайн xml, где вы помещаете эту панель поиска, а также код активности java - person Janku; 08.06.2018
comment
на самом деле то, что я хотел сделать, это когда я установил прогресс для панели поиска, например 16, чтобы большой палец был там вверху по умолчанию в соответствии с номером прогресса без прокрутки панели поиска. - person Janku; 08.06.2018