本文主要记录一些零碎的东西
公司UI想出一个SeekBar,中间是0 ,往左是负的,往右是正的,自带的完全无法满足,只能自己撸了,想了一下,有些思路
主要是Canvas 类画直线,画圆,画圆角矩形,看看效果
效果看着还可以,因为要支持最左边的点是0,所以设置了两种模式的切换,
跟随手势移动的处理:
touch事件,判断touch点是否在Thumb上,如果是在拉动圆点
/**
* 判断是否 touch 在 seekBar thumb 上
*
* @param event
* @return
*/
private boolean isTouchingTarget(MotionEvent event) {
isTouchLegal = event.getRawX() > progressPosition - DEFAULT_TOUCH_TARGET_SIZE
&& event.getRawX() < progressPosition + DEFAULT_TOUCH_TARGET_SIZE;
// Log.i("slack", "isTouchLegal " + isTouchLegal);
return isTouchLegal;
}
根据手在屏幕上的位置以及该View的布局(宽度高度)计算出当前的progress
/**
* 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) {
if (mIsCenterState) {
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;
}
} else {
int centerX = getWidth() / 2;
float min = centerX - width / 2;// the start point
float max = centerX + width / 2;// the end point
if (value >= max) {
return maxProgress;
} else if (value <= min) {
return minProgress;
} else {
return (maxProgress - minProgress) * (value - min) / width ;
}
}
}
移动时增加自定义动画
/**
* 自定义动画 ofFloat(Object target, String propertyName, float... values)
* 第一个参数用于指定这个动画要操作的是哪个控件
* 第二个参数用于指定这个动画要操作这个控件的哪个属性
* 第三个参数是可变长参数,这个就跟ValueAnimator中的可变长参数的意义一样了,就是指这个属性值是从哪变到哪
* 对于自定义的属性,d第二个参数需要提供setXXX 方法,like: public void setMThumbRadius(int mThumbRadius)
* set方法 属性的第一个字母记得要大写 ! ObjectAnimator.ofInt , ofInt 对应参数的类型,如果float 为ofFloat
*/
private ObjectAnimator getTargetAnimator(boolean touching) {
final ObjectAnimator anim = ObjectAnimator.ofFloat(this,
"mThumbRadius",
mThumbRadius,
touching ? mThumbPressedRadius : mThumbNormalRadius);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// Log.i("slack","onAnimationUpdate...");
postInvalidate(); // 在子线程中使用刷新View
}
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Log.i("slack","onAnimationEnd...");
anim.removeAllListeners();
}
});
anim.setInterpolator(new AccelerateInterpolator());
return anim;
}
public void setMThumbRadius(float mThumbRadius) {
// Log.i("slack","setmThumbRadius...");
this.mThumbRadius = mThumbRadius;
}
看看完整代码 com.cl.slack.seekbar.CenterSeekBar
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
/**
* 从中间可以向两边滑动 左负右正
* Created by slack on 2016/12/12 19:00.
*/
public class CenterSeekBar extends View {
private static final int DEFAULT_TOUCH_TARGET_SIZE = 40;
private final int DEFAULT_TEXT_PADDING = 10;
private Paint paint;
private float width = 800; // need <= getWidth()
/**
* progress start max
*/
private int minProgress = 0;
/**
* progress end max
*/
private int maxProgress = 100;
/**
* 进度条的颜色 底色 背景色
*/
@ColorInt
private int progressBackColor = Color.BLACK;
/**
* 进度条的底色 高度
*/
private float progressBackHeight = 10;
/**
* 进度条 底色 圆角矩形边框 描边
*/
@ColorInt
private int progressFrameColor = Color.WHITE;
/**
* 进度条圆角矩形边框 高度
*/
private float progressFrameHeight = 3;
/**
* 进度条的颜色
*/
@ColorInt
private int progressColor = Color.GREEN;
/**
* 进度条的 高度
*/
private float progressHeight = 20;
/**
* 如果0在中间,负进度条的颜色
*/
@ColorInt
private int progressMinusColor = Color.RED;
/**
* current progress
*/
private int progress = 50;
/**
* seekBar Thumb normal radius
*/
private float mThumbNormalRadius = 14;
/**
* seekBar Thumb radius when touched
*/
private float mThumbPressedRadius = 24;
/**
* seekBar Thumb color
*/
@ColorInt
private int mThumbColor = Color.BLUE;
/**
* progress 字体大小
*/
private float mTextSize = 40;
/**
* progress 字体 color
*/
@ColorInt
private int mTextColor = Color.WHITE;
/**
* progress 字体 背景 color
*/
@ColorInt
private int mTextBackColor = 0x7DD2D3D4;
/**
* progress 字体 背景 radius
*/
private float mTextBackRadius = 10;
/**
* 判断是否是 0 在中间
*/
private boolean mIsCenterState = false;
private float mThumbRadius = mThumbNormalRadius;
private float progressPosition;
private boolean isTouchLegal = false;
private ObjectAnimator mAnimator; // seekBar Thumb Animator
private RectF mTextRectF,mBackRectF,mProgressRectF;
private OnSeekBarProgressListener mOnSeekBarProgressListener;
private OnSeekBarFinishedListener mOnSeekBarFinishedListener;
public CenterSeekBar(Context context) {
this(context, null);
}
public CenterSeekBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CenterSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
if (attrs != null) {
TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs,
R.styleable.CenterSeekBar, 0, 0);
maxProgress = styledAttrs.getInteger(R.styleable.CenterSeekBar_maxProgress,100);
minProgress = styledAttrs.getInteger(R.styleable.CenterSeekBar_minProgress,0);
width = styledAttrs.getDimension(R.styleable.CenterSeekBar_width,800);
mIsCenterState = styledAttrs