最近需要写自定义ViewGroup,发现直接写事件处理很麻烦使用ViewDragHelper处理就很简单,ViewDragHelper是用来处理子view的事件处理工具:
在onMeasure(int widthMeasureSpec, int heightMeasureSpec)中需要做子view的测量和自己的测量:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//测量子view的大小
measureChildren(widthMeasureSpec, heightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
height = getChildAt(0).getMeasuredHeight();
}
//设置自己的宽高
setMeasuredDimension(width, height);
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
在onLayout(boolean changed, int l, int t, int r, int b)中做子view的位子布局设置:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//int l, int t, int r, int b参数为自己的范围,即布局的矩形范围
Log.e("onLayout", "int l, int t, int r, int b=" + l + ":" + t + ":" + r + ":" + b);
final int count = getChildCount();
int xpos = getPaddingLeft();
int ypos = getPaddingTop();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
//调用layout确认子view的位置
child.layout(xpos + i * space, ypos, xpos + i * space + child.getMeasuredWidth(),
ypos + child.getMeasuredHeight());
}
}
}
重写onTouchEvent(MotionEvent event)处理子view的事件处理(也可以重写onInterceptTouchEvent(MotionEvent ev)去拦截事件等)
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
ViewDragHelper的创建,重写一些需要的方法:
mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View view, int arg1) {//判断自view是否能捕获(能否移动)
return true;
}
@Override
public int clampViewPositionHorizontal(View view, int left, int dx) {
int count = getChildCount();
int index = indexOfChild(view);
//计算边界[a,b]
int a = index * space;
int b = a;
if (index >0) {
b = getMeasuredWidth() - (count - index) * space;
}
left = Math.max(a, Math.min(left, b));
return left;
}
});
}
这样就能简单的水平移动
弹性滑动的实现:
调用:
在ViewDragHelper 回调中调用 (应为这是设置CapturedView)
//fling设置两个边界一个是轻滑动,一个是重滑动
mViewDragHelper.flingCapturedView();
mViewDragHelper.settleCapturedViewAt();
或者调用:
smoothSlideViewTo(View child, int finalLeft, int finalTop)
注意需要在布局中实现:
@Override
public void computeScroll() {
if(mViewDragHelper.continueSettling(true)){
invalidate();
}
}