Добавить динамический текст через Android SeekBar thumb

Я пытаюсь сделать этот обычай SeekBar в Android 2.2, и все, что я делаю, кажется неправильным! Я пытаюсь отобразить значение поиска на большом пальце изображения SeekBar. Есть ли у кого-нибудь опыт с этим?

Ответ 1

Я предполагаю, что вы уже расширили базовый класс, поэтому у вас есть что-то вроде:

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

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

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

Теперь вы переопределяете метод onDraw с помощью своего собственного кода. Вставьте следующее:

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

Теперь вы хотите нарисовать текст рядом с большим пальцем, но нет удобного способа получить х-позицию большого пальца. Нам просто нужна небольшая математика.

@Override
protected void onDraw(Canvas c) {
    super.onDraw(c);
    int thumb_x = ( (double)this.getProgress()/this.getMax() ) * (double)this.getWidth();
    int middle = this.getHeight()/2;
    // your drawing code here, ie Canvas.drawText();
}

Ответ 2

seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                int val = (progress * (seekBar.getWidth() - 2 * seekBar.getThumbOffset())) / seekBar.getMax();
                text_seekbar.setText("" + progress);
                text_seekbar.setX(seekBar.getX() + val + seekBar.getThumbOffset() / 2);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                text_seekbar.setVisibility(View.VISIBLE);

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                text_seekbar.setVisibility(View.GONE);
            }
        });

Ответ 3

Это сработало для меня

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int val = (progress * (seekBar.getWidth() - 2 * seekBar.getThumbOffset())) / seekBar.getMax();
_testText.setText("" + progress);
_testText.setX(seekBar.getX() + val + seekBar.getThumbOffset() / 2);
}

Ответ 4

Эй, я нашел другое решение, кажется более простым:

 private void setText(){
    int progress = mSeekBar.getProgress();
    int max= mSeekBar.getMax();
    int offset = mSeekBar.getThumbOffset();
    float percent = ((float)progress)/(float)max;
    int width = mSeekBar.getWidth() - 2*offset;

    int answer =((int)(width*percent +offset - mText.getWidth()/2));
    mText.setX(answer);

}


@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    setText();
    mText.setText(""+progress);
}

Ответ 5

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

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

Сначала вы должны спроектировать макет, который будет установлен как перенос большого пальца.

layout_seekbar_thumb.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="@dimen/seekbar_thumb_size"
        android:layout_height="@dimen/seekbar_thumb_size"
        android:background="@drawable/ic_seekbar_thumb_back"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvProgress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:textColor="#000000"
            android:textSize="14sp" />

    </LinearLayout>

</LinearLayout>

Здесь seekbar_thumb_size может быть любого небольшого размера согласно вашему требованию. Я использовал 30dp здесь. Для фона вы можете использовать любой подходящий/значок по вашему выбору.

Теперь вам нужно, чтобы это представление было настроено как thumb drawable, поэтому получите его со следующим кодом:

View thumbView = LayoutInflater.from(YourActivity.this).inflate(R.layout.layout_seekbar_thumb, null, false);

Здесь я предлагаю инициализировать это представление в onCreate(), поэтому нет необходимости раздувать его снова и снова.

Теперь установите этот вид как увеличенный палец при изменении хода seekBar. Добавьте в свой код следующий код:

public Drawable getThumb(int progress) {
        ((TextView) thumbView.findViewById(R.id.tvProgress)).setText(progress + "");

        thumbView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        Bitmap bitmap = Bitmap.createBitmap(thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        thumbView.layout(0, 0, thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight());
        thumbView.draw(canvas);

        return new BitmapDrawable(getResources(), bitmap);
}

Теперь вызовите этот метод из onProgressChanged().

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

                // You can have your own calculation for progress                    
                seekBar.setThumb(getThumb(progress));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

Примечание: Также вызывайте метод getThumb(), когда вы инициализируете seekBar, чтобы инициализировать его значением по умолчанию.

При таком подходе вы можете иметь любой пользовательский вид изменения хода.

Ответ 6

Я использовал эту библиотеку для создания выпадающего текстового вида и программным образом превратил эту программу в палец.

https://github.com/amulyakhare/TextDrawable

Код выглядит примерно так:

seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
            String dynamicText = String.valueOf(progress);
            TextDrawable drawable = TextDrawable.builder()
                    .beginConfig()
                    .endConfig()
                    .buildRoundRect(dynamicText , Color.WHITE ,20);
            seekBar.setThumb(drawable);

        }
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });

Ответ 7

Этот код выровняет ваш центр TextView в вашем центре тэгов SeekBar. Ширина YOUR_TEXT_VIEW должна быть wrap_content в xml.

Надеюсь, что этот код вам поможет.

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
       YOUR_TEXT_VIEW.setText(Integer.toString(progress));
       double pourcent = progress / (double) seekBar.getMax();
       int offset = seekBar.getThumbOffset();
       int seekWidth = seekBar.getWidth();
       int val = (int) Math.round(pourcent * (seekWidth - 2 * offset));
       int labelWidth = YOUR_TEXT_VIEW.getWidth();
       YOUR_TEXT_VIEW.setX(offset + seekBar.getX() + val
                 - Math.round(pourcent * offset)
                 - Math.round(pourcent * labelWidth/2));
}

Ответ 8

Работает неплохо для меня
есть небольшой hardcode)
напишите улучшения, которые smbd может иметь

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.AppCompatSeekBar;
import android.util.AttributeSet;
import android.util.TypedValue;

public class CustomSeekBar extends AppCompatSeekBar {

    @SuppressWarnings("unused")
    private static final String TAG = CustomSeekBar.class.getSimpleName();

    private Paint paint;
    private Rect bounds;

    public String dimension;

    public CustomSeekBar(Context context) {
        super(context);
        init();
    }

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

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

    private void init(){
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setTextSize(sp2px(14));

        bounds = new Rect();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        String label = String.valueOf(getProgress()) + dimension;
        paint.getTextBounds(label, 0, label.length(), bounds);
        float x = (float) getProgress() * (getWidth() - 2 * getThumbOffset()) / getMax() +
            (1 - (float) getProgress() / getMax()) * bounds.width() / 2 - bounds.width() / 2
            + getThumbOffset() / (label.length() - 1);
        canvas.drawText(label, x, paint.getTextSize(), paint);
    }

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

Ответ 9

Я создал этот пример, чтобы показать, как textview должен поддерживаться для разных типов размера экрана и как вычислять реальную позицию Thumb, потому что иногда позиция может быть 0.

public class CustomProgressBar extends RelativeLayout implements AppCompatSeekBar.OnSeekBarChangeListener {

    @BindView(R.id.userProgressBar)
    protected AppCompatSeekBar progressSeekBar;
    @BindView(R.id.textPorcent)
    protected TextView porcent;
    @BindView(R.id.titleIndicator)
    protected TextView title;

    public CustomProgressBar(Context context) {
        super(context);
        init();
    }

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

    private void init() {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.custom_progressbar_view, this, true);
        ButterKnife.bind(this);
        setColors(R.color.green, R.color.progress_bar_remaining);
        progressSeekBar.setPadding(0, 0, 0, 0);
        progressSeekBar.setOnSeekBarChangeListener(this);
    }

    private void setPorcentTextViewPosition(float widthView) {
        int width = CoreUtils.getScreenSize().x;
        float xPosition = ((float) progressSeekBar.getProgress() / 100) * width;
        float finalPosition = xPosition - (widthView / 2f);
        if (width - xPosition < widthView) {
            porcent.setX(width - widthView);
        } else if (widthView < finalPosition) {
            porcent.setX(finalPosition);
        }
    }

    public void setColors(int progressDrawable, int remainingDrawable) {
        LayerDrawable layer = (LayerDrawable) progressSeekBar.getProgressDrawable();
        Drawable background = layer.getDrawable(0);
        Drawable progress = layer.getDrawable(1);

        background.setColorFilter(ContextCompat.getColor(getContext(), remainingDrawable), PorterDuff.Mode.SRC_IN);
        progress.setColorFilter(ContextCompat.getColor(getContext(), progressDrawable), PorterDuff.Mode.SRC_IN);
    }

    public void setValues(int progress, int remaining) {
        int value = (progress * remaining) / 100;
        progressSeekBar.setMax(remaining);
        porcent.setText(String.valueOf(value).concat("%"));

        porcent.post(new Runnable() {
            @Override
            public void run() {
                setPorcentTextViewPosition(porcent.getWidth());
            }
        });
        progressSeekBar.setProgress(value);
    }

    public void setTitle(String title) {
        this.title.setText(title);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
}