seekbar(seekbar滑块自定义)
seekbar属性设置
SeekBar是滑动条组件,在音视频的播放器的下面经常看到。
该组件的属性:
·android:max设置进度条的最大值 。对应方法:setMax(int max);max=100,代表它的取值范围是0-100,共101个值;
·android:progress设置默认的进度值 对应有方法:setProgress(int progress);
·android:设置默认缓冲值 对应的方法setSecondaryProgress(int? secondaryProgresss );
·android:progressDrawable设置进度条的图片
·android:thumb滑块属性,应该对应是一个drawable资源;
常用的方法:
·getMax()获取最大范围值
·getProgress()获取当前进度值
·setMax(int)设置范围最大值
·setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l)。监听器
SeekBar.OnSeekBarChangeListener中可以监听三种事件:数值的改变(onProgressChanged)、开始拖动(onStartTrackingTouch)、停止拖动(onStopTrackingTouch)。
自定义 SeekBar 样式 详解
android:maxHeight 背景高度
android:progressDrawable 进度条背景
android:thumb 进度thumb(拖块)
android:splitTrack thumb是否切割seekbar背景,默认true,会看到thumb周围区域被切割,效果如下(为了效果明显,背景高度特意改高了)
seekbar_bg.xml
seekbar_thumb.xml
可以不指定android:thumb 指定 android:thumbTint来改变thumb颜色,按下/点击有系统默认动效。
前后间距问题:
reference:
正负、中间向两侧滑动的seekbar
由于项目需要,设计了一个可以正负滑动的seekbar,满足获取正负数值的需要
/**
* 从中间可以向两边滑动 左负右正
* p
* Created by zhangjian on 2019/10/15 09:33
*/
public class CenterSeekBarView extends View {
? ? private static final int DEFAULT_TOUCH_TARGET_SIZE = 100;
? ? private final Paint paint;
? ? private float minUnit = 0.1f;
? ? private int coefficient = 10;//增加的系数
? ? private boolean canMove = false;
? ? private float width = 400; // need = getWidth()
? ? /**
? ? * progress start max
? ? */
? ? private int minProgress = 0;
? ? /**
? ? * progress end max
? ? */
? ? private int maxProgress = 100;
? ? /**
? ? * 进度条的颜色 底色 背景色
? ? */
? ? @ColorInt
? ? private int progressBackColor;
? ? /**
? ? * 进度条的颜色
? ? */
? ? @ColorInt
? ? private int progressColor;
? ? /**
? ? * current progress
? ? */
? ? private int progress = 0;
? ? /**
? ? * seekBar Thumb normal radius
? ? */
? ? private float mThumbRadius = 20;
? ? private float progressPosition;
? ? private boolean isTouchLegal = false;
? ? private RectF mBackRectF, mProgressRectF;
? ? private int mThumbDrawColor;
? ? private OnSeekBarChangeListener mOnSeekBarChangeListener;
? ? public CenterSeekBarView(Context context) {
? ? ? ? this(context, null);
? ? }
? ? public CenterSeekBarView(Context context, AttributeSet attrs) {
? ? ? ? this(context, attrs, 0);
? ? }
? ? public CenterSeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(context, attrs, defStyleAttr);
? ? ? ? paint = new Paint();
? ? ? ? paint.setAntiAlias(true);
? ? ? ? progressBackColor = Color.parseColor("#C2C2C2");
? ? ? ? progressColor = Color.parseColor("#4388FF");
? ? ? ? mThumbDrawColor = Color.parseColor("#4388FF");
? ? ? ? mBackRectF = new RectF();
? ? ? ? mProgressRectF = new RectF();
? ? }
? ? @Override
? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec);
? ? ? ? width = getMeasuredWidth() - SizeUtils.dp2px(30);
? ? }
? ? public CenterSeekBarView setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
? ? ? ? mOnSeekBarChangeListener = l;
? ? ? ? return this;
? ? }
? ? public void delProgress() {
? ? ? ? setProgress(progress - (int) (minUnit * coefficient));
? ? }
? ? public void addProgress() {
? ? ? ? setProgress(progress + (int) (minUnit * coefficient));
? ? }
? ? public void reset() {
? ? ? ? setProgress(minProgress);
? ? }
? ? public void setProgress(int progress) {
? ? ? ? if (!canMove){
? ? ? ? ? ? if (mOnSeekBarChangeListener != null) {
? ? ? ? ? ? ? ? mOnSeekBarChangeListener.onError();
? ? ? ? ? ? }
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (progress = maxProgress progress = minProgress - maxProgress) {
? ? ? ? ? ? this.progress = progress;
? ? ? ? ? ? if (mOnSeekBarChangeListener != null) {
? ? ? ? ? ? ? ? mOnSeekBarChangeListener.onProgress((float) progress / coefficient);
? ? ? ? ? ? }
? ? ? ? ? ? invalidate();
? ? ? ? }
? ? }
? ? public void setCanMove(boolean canMove) {
? ? ? ? this.canMove = canMove;
? ? }
? ? @Override
? ? protected void onDraw(Canvas canvas) {
? ? ? ? super.onDraw(canvas);
//? ? ? ? Log.i("slack","onDraw... " + mThumbRadius);
? ? ? ? int centerX = getWidth() / 2; // x 是center
? ? ? ? int centerY = getHeight() / 2; // y 是 2/3 高度
? ? ? ? float startX = centerX - width / 2;
? ? ? ? // draw background line
? ? ? ? paint.setColor(progressBackColor);
? ? ? ? /**
? ? ? ? * 进度条的 高度
? ? ? ? */
? ? ? ? float progressHeight = 9;
? ? ? ? paint.setStrokeWidth(progressHeight);
? ? ? ? paint.setStyle(Paint.Style.FILL); // 实心
? ? ? ? mBackRectF.left = startX;
? ? ? ? mBackRectF.top = centerY - progressHeight;
? ? ? ? mBackRectF.right = startX + width;
? ? ? ? mBackRectF.bottom = centerY;
? ? ? ? /**
? ? ? ? * progress 字体 背景 radius
? ? ? ? */
? ? ? ? canvas.drawRoundRect(mBackRectF, 10, 10, paint);
? ? ? ? paint.setStyle(Paint.Style.FILL);
? ? ? ? paint.setColor(progressColor);
? ? ? ? paint.setStrokeWidth(progressHeight);
? ? ? ? startX = centerX;
? ? ? ? progressPosition = startX + (int) ((progress * (width / 2f) / (maxProgress - minProgress)));
? ? ? ? mProgressRectF.top = centerY - progressHeight;
? ? ? ? mProgressRectF.bottom = centerY;
? ? ? ? if (progress 0) {
? ? ? ? ? ? mProgressRectF.left = startX;
? ? ? ? ? ? mProgressRectF.right = progressPosition;
? ? ? ? } else {
? ? ? ? ? ? mProgressRectF.left = progressPosition;
? ? ? ? ? ? mProgressRectF.right = startX;
? ? ? ? }
? ? ? ? canvas.drawRoundRect(mProgressRectF, 10, 10, paint);
? ? ? ? // draw point
? ? ? ? paint.setColor(mThumbDrawColor);
? ? ? ? canvas.drawCircle(progressPosition, centerY - progressHeight / 2, mThumbRadius, paint);
? ? }
? ? private long mLastTime;
? ? @Override
? ? public boolean onTouchEvent(MotionEvent event) {
? ? ? ? if (!isEnabled()) {
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? if (canMove){
? ? ? ? ? ? ? ? ? ? checkTouchingTarget(event);
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? if (mOnSeekBarChangeListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? mOnSeekBarChangeListener.onError();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? ? ? ? if (isTouchLegal) {
? ? ? ? ? ? ? ? ? ? int tempProgress = (int) clamp((int) event.getRawX() - getLeft());
? ? ? ? ? ? ? ? ? ? if (tempProgress == progress) {
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? progress = tempProgress;
? ? ? ? ? ? ? ? ? ? long currentTime = System.currentTimeMillis();
? ? ? ? ? ? ? ? ? ? if (currentTime - mLastTime 10) {
? ? ? ? ? ? ? ? ? ? ? ? // 刷新 FPS 不超过 20 fps
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? mLastTime = currentTime;
? ? ? ? ? ? ? ? ? ? invalidate(); // 在UI线程中使用 刷新View
? ? ? ? ? ? ? ? ? ? if (mOnSeekBarChangeListener != null) {
? ? ? ? ? ? ? ? ? ? ? ? mOnSeekBarChangeListener.onProgress((float) progress / coefficient);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? invalidate();
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return true;
? ? }
? ? /**
? ? * if touch , seekBar Thumb Animation
? ? */
? ? private void checkTouchingTarget(MotionEvent event) {
? ? ? ? if (isTouchingTarget(event)) {
? ? ? ? ? ? postInvalidate();
? ? ? ? }
? ? }
? ? public void setMaxProgress(int maxProgress) {
? ? ? ? this.maxProgress = maxProgress * coefficient;
? ? }
? ? /**
? ? * 判断是否 touch 在 seekBar thumb 上
? ? *
? ? * @param event
? ? * @return
? ? */
? ? private boolean isTouchingTarget(MotionEvent event) {
? ? ? ? float location = progressPosition + getLeft();
? ? ? ? isTouchLegal = event.getRawX() location - DEFAULT_TOUCH_TARGET_SIZE
? ? ? ? ? ? ? ? event.getRawX() location + DEFAULT_TOUCH_TARGET_SIZE;
? ? ? ? return isTouchLegal;
? ? }
? ? /**
? ? * return? progress
? ? * -maxProgress? ? ? ? ? minProgress? ? ? ? ? ? ? maxProgress
? ? * \------------------------0---------------------------\
? ? * min? ? ? ? ? ? ? ? ? center? ? touch--\? ? ? ? ? max
? ? * (min center touch max are positions in the screen)
? ? * touch progress = (touch - center) / (max - center) * maxProgress;
? ? */
? ? private float clamp(int value) {
? ? ? ? int centerX = getWidth() / 2;
? ? ? ? float min = centerX - width / 2;// the start point
? ? ? ? float max = centerX + width / 2;// the end point
? ? ? ? if (value centerX) {
? ? ? ? ? ? if (value = max) {
? ? ? ? ? ? ? ? return maxProgress;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return (int) ((maxProgress - minProgress) * (value - centerX) / (width / 2f));
? ? ? ? ? ? }
? ? ? ? } else if (value centerX) {
? ? ? ? ? ? if (value = min) {
? ? ? ? ? ? ? ? return -maxProgress;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return (int) ((maxProgress - minProgress) * (value - centerX) / (width / 2f));
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? return minProgress;
? ? ? ? }
? ? }
? ? public interface OnSeekBarChangeListener {
? ? ? ? void onProgress(float progress);
? ? ? ? void onError();
? ? }
}
android开发中,seekBar在拖动时进度会改变,如何让音乐播放进度随之改变?
seekbar.setOnSeekBarChangeListener(new seekbarListener());
//这个监听seekbar变化的,一旦有变,变化到哪progress表示
private class seekbarListener implements OnSeekBarChangeListener{
@Override
public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) {
if(fromUser==true){
mediaplay.seekTo(progress);//这里就是音乐播放器播放的位子
}
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
}
还有就是seekbar的进度条变化用Handler更新,
Android SeekBar,动态显示进度且随SeekBar一起移动
花了点时间做,其实这个东西本没有什么,主要的问题就是在于seekBar不是顶格的,存在一个空隙,这个空隙又不知道值是多少,所以这个很难计算,后来去看了资料,paddingStart = 0dp,PaddingEnd=0dp 可以使进度条填充到整个界面,但也不大符合需求,所以设定paddingStart = 15dp,既能不改变原来seekbar的效果,也可以知道这个间隙是多少。
这里就是计算具体的textview位置的地方了
textview的文本是固定宽度的,动态的太难控制了,不是这种简单的操作能够搞定的。
seekbar的宽度就随意了,注意设置下paddingStart 和 paddingEnd。
xml 如下:
好了效果实现了,这种实现方式算是比较简单了。