【发布时间】:2017-01-21 01:51:07
【问题描述】:
我有一个listview 和seekbar,每个seekbar 代表产品价值的100%。通过移动seekbar 可以更改% 值,我想在用户拖动seekbar 时沿搜索栏显示值的变化。我确实不希望添加另一个更新值的文本框。
我更多地关注在搜索栏指针顶部显示一个小视图的选项,它出现 onStartTracking 并消失 onStopTracking 事件。
有没有办法做到这一点?
【问题讨论】:
我有一个listview 和seekbar,每个seekbar 代表产品价值的100%。通过移动seekbar 可以更改% 值,我想在用户拖动seekbar 时沿搜索栏显示值的变化。我确实不希望添加另一个更新值的文本框。
我更多地关注在搜索栏指针顶部显示一个小视图的选项,它出现 onStartTracking 并消失 onStopTracking 事件。
有没有办法做到这一点?
【问题讨论】:
这是一种简单的方法,
textView
seekBar的移动改变它的位置
setX()定位它setY() 指定为 Y 位置textView Visibility 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);
}
}
在您的 XML 中设置/创建您的 SeekBar
<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) {
}
});
【讨论】:
val offset = (seekBar.width - seekBar.paddingLeft - seekBar.paddingRight) * progress / seekBar.max 然后textView.x = seekBar.x + seekBar.paddingLeft + offset
textView.x = [...] - textView.width / 2 使文本视图居中。
在你的 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文件中,改变seekbar的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) {
}
});
【讨论】:
使文本视图真正与拇指位置 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);
}
【讨论】:
试试我找到的这个离散搜索栏库here
最简单的方法是使用 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"/>
【讨论】:
检查此library。您可以使用“单拇指到真范围搜索栏”。
【讨论】:
对于大多数情况,公认的答案可能已经足够了。但是,如果您想要精确以使文本恰好位于搜索栏拇指的中间,则必须进行更多计算。这是因为文本的宽度不同。假设您要显示 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)
}
【讨论】: