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

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

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

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(); } 
 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); } }); 

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

 @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); } 

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

  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); } 

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

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) { } }); 

Этот следующий код выравнивает ваш центр TextView центре SeekBar пальца 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)); } 

Работает неплохо для меня
Есть небольшой 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()); } } 

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

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

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

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="@color/appColorBlack" 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() поэтому нет необходимости раздувать его снова и снова.

Теперь установите это представление как thumb drawable при изменении хода 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 чтобы инициализировать его значением по умолчанию.

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

Я создал этот пример, чтобы показать, как 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) { } }