需求:部分场景下,防止用户误操作触发按钮,通过滑动的方式完成用户的点击事件。
自定义组件实现思路:
1、定义一View组件,该组件可以通过手势拖动在其父类组件上滑动。
2、定义一ViewGroup组件。初始化时,该组件被View组件完全覆盖。
自定义组件实现:
1、实现组件SlideCover(上方完全覆盖的View):
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize= MeasureSpec.getSize(widthMeasureSpec);
int heightSize= MeasureSpec.getSize(heightMeasureSpec);
int widthMode= MeasureSpec.getMode(widthMeasureSpec);
int heightMode= MeasureSpec.getMode(heightMeasureSpec);
if(heightMode== MeasureSpec.AT_MOST){//如果是wrap_content布局以字体的高度作为控件高度
setMeasuredDimension(MeasureSpec.makeMeasureSpec(widthSize, widthMode), MeasureSpec.makeMeasureSpec((int) (fontMetrics.bottom - fontMetrics.top) + coverPadding * 2, heightMode));
}else {
setMeasuredDimension(MeasureSpec.makeMeasureSpec(widthSize, widthMode), MeasureSpec.makeMeasureSpec(heightSize + coverPadding * 2, heightMode));
}
}
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
//计算文字中心点高度
float height= getMeasuredHeight() / 2-fontMetrics.top/2-fontMetrics.bottom/2;
//绘制箭头
canvas.drawText(">>>>", getMeasuredWidth() * left_margin, height, paint);
if(null!=coverText){
canvas.drawText(coverText, getMeasuredWidth() / 2,height, paint);
}
}
拖动事件:
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()== MotionEvent.ACTION_DOWN){//手指按下后的点击事件
xTouch=event.getRawX();
}else if(event.getAction()== MotionEvent.ACTION_MOVE){//移动中的点击事件
xSlideOffset=event.getRawX()-xTouch;
update();
}else if(event.getAction()== MotionEvent.ACTION_UP){
finish();
}
return true;
}
2.SlideButton实现
属性定义
//viewgroup背景的颜色
private int bgColor;
//viewgroup的字体大小
private int bgTextsize;
//viewgroup的文字内容
private String bgText;
//viewgroup的文字颜色
private int bgTextColor;
//当移动到哪个位置时结束
private float offSetFinish;
//SlideCover的背景颜色
private Drawable coverBackground;
//SlideCover的字体大小
private int coverTextsize;
//SlideCover的字体内容
private String coverText;
//SlideCover的字体颜色
private int coverTextColor;
//SlideCover的字体Padding
private int coverPadding=0;
/**
* 绘制paint
*/
private Paint bgPaint;
/**
* viewgourp的字体测量参数
*/
private Paint.FontMetrics bgFontMetrics;
/**
* 子控件
*/
private SlideCover slideCover;
/**
* slideCover点下去的坐标
*/
private float xTouch=0;
/**
* slideCover滑动时的偏移量
*/
private float xSlideOffset=0;
/**
* 滑动监听
*/
private SlideListner slideListner;
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量子控件
measureChildren(widthMeasureSpec, heightMeasureSpec);
//获取子控件slideCover
SlideCover slideCover= (SlideCover) getChildAt(0);
setMeasuredDimension(slideCover.getMeasuredWidth(),slideCover.getMeasuredHeight());
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//判断偏移量是否小于零,小于零偏移量设为0,否则会向左移动
if(xSlideOffset<0){
xSlideOffset=0;
}else if(xSlideOffset>getMeasuredWidth()){
xSlideOffset=getMeasuredWidth();
}
//子控件位置
slideCover.layout((int)(0+xSlideOffset),0,(int)(getMeasuredWidth()+xSlideOffset),getMeasuredHeight());
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
bgPaint.setColor(bgColor);
//绘制矩形
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), bgPaint);
bgPaint.setColor(bgTextColor);
//绘制文字
float height= getMeasuredHeight() / 2-bgFontMetrics.top/2-bgFontMetrics.bottom/2;
if(bgText!=null){
canvas.drawText(bgText, getMeasuredWidth() / 2,height, bgPaint);
}
}
每次slidecover控件拖动时需要调用slidebutton的requestLayout方法,实现拖动的展示效果。