Android Seekbar показывает значение прогресса вдоль панели поиска

У меня есть listview с seekbar, каждый seekbar представляет 100% стоимости продукта. Перемещая seekbar, можно изменить значение%, я хочу показать изменение значения вдоль панели поиска, пока пользователь перетаскивает seekbar. Я не хочу добавить еще одно текстовое поле, в котором значение обновляется.

Я больше смотрю на варианты, чтобы показать небольшой вид поверх указателя панели поиска, который появляется onStartTracking и исчезает onStopTracking событие.

Есть ли способ добиться этого?


person user2622786    schedule 21.01.2017    source источник


Ответы (6)


Вот один простой способ,

  • Добавьте textView в свой XML
  • Измените его положение движением seekBar
  • Это поместит его с помощью setX()
  • Если вы хотите, вы также можете указать setY() для его позиции Y.
  • Если вы хотите скрыть, напишите немного логики и сделайте textView Видимость GONE, когда вам нужно.

пример:

seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

                    int val = (progress * (seekBar.getWidth() - 2 * seekBar.getThumbOffset())) / seekBar.getMax();
                    textView.setText("" + progress);
                    textView.setX(seekBar.getX() + val + seekBar.getThumbOffset() / 2);
                    //textView.setY(100); just added a value set this properly using screen with height aspect ratio , if you do not set it by default it will be there below seek bar 

                }

или вы можете использовать Paint со своим собственным классом SeekBar без каких-либо TextView

Создать класс

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.SeekBar;


public class MySeekBar extends SeekBar {
    public MySeekBar (Context context) {
        super(context);
    }

    public MySeekBar (Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MySeekBar (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas c) {
        super.onDraw(c);
        int thumb_x = (int) (( (double)this.getProgress()/this.getMax() ) * (double)this.getWidth());
        float middle = (float) (this.getHeight());

        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setTextSize(20);
        c.drawText(""+this.getProgress(), thumb_x, middle, paint);
    }
}

Установите/создайте свой SeekBar в своем XML

  <yourPackageName.MySeekBar
            android:id="@+id/my_seek_bar"
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginTop="26dp"
            android:max="10"/>

Теперь из вашей деятельности

seekBar = (MySeekBar) findViewById(R.id.my_seek_bar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
});
person Charuක    schedule 21.01.2017
comment
Супер, спасибо! Я думаю, что правильное положение текстового представления вычисляется следующим образом (Kotlin): val offset = (seekBar.width - seekBar.paddingLeft - seekBar.paddingRight) * progress / seekBar.max, а затем textView.x = seekBar.x + seekBar.paddingLeft + offset - person thando; 02.10.2019
comment
PS: плюс textView.x = [...] - textView.width / 2 для центрирования текстового представления. - person thando; 02.10.2019

добавьте текстовое представление в свой XML-файл, вы можете использовать linrarlayout следующим образом:

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <SeekBar
            android:id="@+id/seekBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:max="1000" />

        <TextView
            android:id="@+id/textView4"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

    </LinearLayout>

и в java-файле измените текст текстового представления в методе onProgressChanged панели поиска:

    SeekBar sk = (SeekBar) findViewById(R.id.seekBar);
    sk.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            TextView t=(TextView)findViewById(R.id.textView4);
            t.setText(String.valueOf(i));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
person amir_a14    schedule 27.08.2018

Чтобы сделать текстовое представление действительно выровненным с центром положения большого пальца X

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
    progressTextView.setText(String.valueOf(progress));

    int width = seekBar.getWidth() - seekBar.getPaddingLeft() - seekBar.getPaddingRight();
    int thumbPos = seekBar.getPaddingLeft() + width * seekBar.getProgress() / seekBar.getMax();

    progressTextView.measure(0, 0);
    int txtW = progressTextView.getMeasuredWidth();
    int delta = txtW / 2;
    progressTextView.setX(seekBar.getX() + thumbPos - delta);
}
person xuanzhui    schedule 20.03.2020

Попробуйте эту дискретную библиотеку панели поиска, которую я нашел здесь

Самый простой выход - использовать Materila Slider, который добавляет для вас метку значения без необходимости кодировать textView для отслеживания.

   <com.google.android.material.slider.Slider
        android:id="@+id/continuous_slider"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:valueFrom="0"
       android:stepSize="1"
        app:labelBehavior="withinBounds"
        android:valueTo="100"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"/>
person Tonnie    schedule 29.05.2021

Проверьте эту библиотеку. Вы можете использовать «полосу поиска диапазона с одним большим пальцем до истины».

person Abhriya Roy    schedule 21.01.2017
comment
Хорошая находка. Пишет, что устарело, но я попробую - person AjCodez; 06.05.2018

Принятый ответ, вероятно, достаточно хорош для большинства ситуаций. Однако, если вам нужна точность, чтобы текст находился ровно посередине большого пальца панели поиска, вам нужно немного больше вычислений. Это связано с тем, что ширина текста отличается. Скажем, вы хотите показывать числа от 0 до 150. Ширина 188 будет отличаться от 111. Из-за этого отображаемый текст всегда будет наклоняться в какую-то сторону.

Способ решить эту проблему - измерить ширину текста, удалить ее из ширины большого пальца панели поиска, разделить на 2 и добавить к результату, который был дан в принятом ответе. Теперь вам все равно, насколько велик диапазон чисел. Вот код:

 override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                    val value = progress * (seekBar.width - 2 * seekBar.thumbOffset) / seekBar.max
                    label.text = progress.toString()
                    label.measure(0, 0)
                    val textWidth =  label.measuredWidth
                    val firstRemainder = seekThumbWidth - textWidth
                    val result = firstRemainder / 2
                    label.x = (seekBar.x + value + result)
                }
person Sermilion    schedule 01.06.2019