上面这个效果就是左右两个布局,往左侧滑,删除显示,往右侧滑,删除隐藏;可以extends HorizontalScrollView来实现,不过extends HorizontalScrollView 就需要去重写onMeasure(测量)和onLayout(摆放),这里就没有extends HorizontalScrollView了,extends的是LinearLayout,并重写dispatchTouchEvent进行事件处理。
1、自定义控件extendsLinearLayout
public class SlidingItemMenuLayout extends LinearLayout {
private Scroller mScroller;
private View leftChild;
private View rightChild;
public SlidingItemMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
//设置水平显现
setOrientation(LinearLayout.HORIZONTAL);
mScroller = new Scroller(getContext(), null, true);
}
}
2、重写dispatchTouchEvent进行事件处理
这里要处理ACTION_DOWN、ACTION_UP、ACTION_MOVE几种类型的动作;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下
//记录开始的x和y
startX = ev.getX();
startY = ev.getY();
super.dispatchTouchEvent(ev);
return true;
case MotionEvent.ACTION_MOVE:
//移动
//dx>0 向右滑动 dx<0向左滑动
dx = ev.getX() - startX;
dy = ev.getY() - startY;
//getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件。如果小于这个距离就不触发移动控件
if (Math.abs(dx) - Math.abs(dy) > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
//滑动的距离不能大于右边的宽度
if (getScrollX() + (-dx) > rightChild.getWidth() || getScrollX() + (-dx) < 0) {
return true;
}
this.scrollBy((int) -dx, 0);
startY = ev.getY();
startX = ev.getX();
return true;
}
break;
case MotionEvent.ACTION_UP:
//抬起
//仅仅只是把滑动的情况和参数描述和记录, 判断当前松开是往左滑还是往右滑
int offset = (getScrollX() / (float) rightChild.getWidth()) > 0.5f ? rightChild.getWidth() - getScrollX() : -getScrollX();
mScroller.startScroll(getScrollX(), getScrollY(), offset, 0);
//进行绘制
invalidate();
startX=0;
startY=0;
dx=0;
dy=0;
break;
}
return super.dispatchTouchEvent(ev);
}
dispatchTouchEvent方法默认是返回false的,通俗的说,返回false代表就是不消费此事件,返回true代表就是消费此事件;
当然了在处理事件的时候还需要获取到对应的子view
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//布局测量完成会调用
int childCount = getChildCount();
if (childCount != 2) {
throw new RuntimeException("child view must tow count");
}
//获取相应的子view
leftChild = getChildAt(0);
rightChild = getChildAt(1);
}
在开启滑动的情况下还会不断的调用computeScroll方法
@Override
public void computeScroll() {
//在开启滑动的情况下(mScroller.startScroll),滑动的过程当中此方法会被不断调用
if(mScroller.computeScrollOffset()){
this.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
postInvalidate();
}
}
其实这里最主要的还是dispatchTouchEvent方法,对于事件的处理。