Я пытаюсь сделать этот обычай SeekBar в Android 2.2, и все, что я делаю, кажется неправильным! Я пытаюсь отобразить значение поиска на большом пальце изображения SeekBar. Есть ли у кого-нибудь опыт с этим?
Добавить динамический текст через Android SeekBar thumb
Ответ 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) {
    }
}

