在 Android 中实现一个滑块(SeekBar)
Posted
技术标签:
【中文标题】在 Android 中实现一个滑块(SeekBar)【英文标题】:Implementing a slider (SeekBar) in Android 【发布时间】:2012-01-27 14:37:16 【问题描述】:我想实现一个滑块,它基本上是两条线,一条垂直,一条水平,穿过屏幕被触摸的地方。我已经成功制作了一个,但我必须解决问题:
-
滑块不是很流畅,移动手指时有一点延迟
如果我放置两个滑块,则不是多点触控,我想同时使用它们
代码如下:
public class Slider extends View
private Controller controller = new Controller();
private boolean initialisedSlider;
private int sliderWidth, sliderHeight;
private Point pointStart;
private Paint white;
private int mode;
final static int VERTICAL = 0, HORIZONTAL = 1, BOTH = 2;
public Slider(Context context)
super(context);
setFocusable(true);
// TODO Auto-generated constructor stub
public Slider(Context context, AttributeSet attrs)
super(context, attrs);
setFocusable(true);
pointStart = new Point();
initialisedSlider = false;
mode = Slider.BOTH;
@Override
protected void onDraw(Canvas canvas)
if(!initialisedSlider)
initialisedSlider = true;
sliderWidth = getMeasuredWidth();
sliderHeight = getMeasuredHeight();
pointStart.x = (int)(sliderWidth/2.0);
pointStart.y = (int)(sliderHeight/2.0);
controller = new Controller(pointStart, 3);
white = new Paint();
white.setColor(0xFFFFFFFF);
canvas.drawLine(controller.getCoordX(),0,
controller.getCoordX(),sliderHeight,
white);
canvas.drawLine(0, controller.getCoordY(),
sliderWidth, controller.getCoordY(),
white);
public boolean onTouchEvent(MotionEvent event)
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction)
case MotionEvent.ACTION_DOWN:
if(isInBounds(X,Y))
updateController(X, Y);
break;
case MotionEvent.ACTION_MOVE:
if(isInBounds(X,Y))
updateController(X, Y);
break;
case MotionEvent.ACTION_UP:
if(isInBounds(X,Y))
updateController(X, Y);
break;
invalidate();
return true;
private boolean isInBounds(int x, int y)
return ((x<=(sliderWidth)) && (x>=(0))
&& (y<=(sliderHeight)) && (y>=(0)));
private void updateController(int x, int y)
switch(mode)
case Slider.HORIZONTAL:
controller.setCoordX(x);
break;
case Slider.VERTICAL:
controller.setCoordY(y);
break;
case Slider.BOTH:
controller.setCoordX(x);
controller.setCoordY(y);
break;
private class Controller
private int coordX, coordY;
Controller()
Controller(Point point, int width)
setCoordX(point.x);
setCoordY(point.y);
public void setCoordX(int coordX)
this.coordX = coordX;
public int getCoordX()
return coordX;
public void setCoordY(int coordY)
this.coordY = coordY;
public int getCoordY()
return coordY;
以及 XML 文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical" >
<TextView
android:layout_
android:layout_
android:text="@string/hello" />
<com.android.lasttest.Slider
android:id="@+id/slider"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
<com.android.lasttest.Slider
android:id="@+id/slider"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
<com.android.lasttest.Slider
android:id="@+id/slider"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
</LinearLayout>
【问题讨论】:
【参考方案1】:如何实现 SeekBar
将 SeekBar 添加到您的布局中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_>
<TextView
android:id="@+id/textView"
android:layout_margin="20dp"
android:layout_
android:layout_/>
<SeekBar
android:id="@+id/seekBar"
android:max="100"
android:progress="50"
android:layout_
android:layout_/>
</LinearLayout>
注意事项
max
是搜索栏可以达到的最高值。默认值为100
。最小值为0
。 xml min
值仅适用于 API 26,但您可以通过编程将 0-100
范围转换为早期版本所需的任何值。
progress
是滑块点(称为“拇指”)的初始位置。
对于垂直 SeekBar,请使用 android:rotation="270"
。
监听代码变化
public class MainActivity extends AppCompatActivity
TextView tvProgressLabel;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set a change listener on the SeekBar
SeekBar seekBar = findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
int progress = seekBar.getProgress();
tvProgressLabel = findViewById(R.id.textView);
tvProgressLabel.setText("Progress: " + progress);
SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener()
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
// updated continuously as the user slides the thumb
tvProgressLabel.setText("Progress: " + progress);
@Override
public void onStartTrackingTouch(SeekBar seekBar)
// called when the user first touches the SeekBar
@Override
public void onStopTrackingTouch(SeekBar seekBar)
// called after the user finishes moving the SeekBar
;
注意事项
如果您在用户移动搜索栏时不需要进行任何更新,那么您可以在onStopTrackingTouch
中更新 UI。
另见
SeekBar Tutorial With Example In Android Studio【讨论】:
关于垂直搜索栏的说明。如果您想避免尺寸问题,请查看以下答案:***.com/a/51728247/6423246【参考方案2】:Android 提供水平滑块
http://developer.android.com/reference/android/widget/SeekBar.html并实现 OnSeekBarChangeListener
http://developer.android.com/reference/android/widget/SeekBar.OnSeekBarChangeListener.html如果您想要垂直搜索栏,请点击此链接
http://hoodaandroid.blogspot.in/2012/10/vertical-seek-bar-or-slider-in-android.html【讨论】:
【参考方案3】:给未来的读者!
从material components android 1.2.0-alpha01开始,你有slider
组件
例如:
<com.google.android.material.slider.Slider
android:id="@+id/slider"
android:layout_
android:layout_
android:valueFrom="20f"
android:valueTo="70f"
android:stepSize="10" />
Release notes Material Design Spec Docs
【讨论】:
以上是关于在 Android 中实现一个滑块(SeekBar)的主要内容,如果未能解决你的问题,请参考以下文章
Android 中的滑块控件... SeekBar 真的是我最好/唯一的选择吗?