效果
仿QQ的滑动删除,效果如下:
实现思路
1.通过include标签引入内容和删除部分
2.需要继承ViewGroup
3.要控制子View的摆放,实现onLayout,需要测量,实现onMeasure
4.在onMeasure需要测量孩子的大小,设置自己的真实大小
5.在onLaout里面初始化子View的摆放
6.接下来就是控制触摸事件了(down,move,up)
7.处理拖地可以在onTouchEvent里面处理,也可以使用工具类ViewDragHelper
代码
public class SweepView extends ViewGroup {
private View mContentView;
private View mDeleteView;
private ViewDragHelper mViewDragHelper;
private int mWidth;
private int mHeight;
private int mDeleteWidth;
private int mDeleteHeight;
public SweepView(Context context) {
this(context, null);
}
public SweepView(Context context, AttributeSet attrs) {
super(context, attrs);
// 两个参数 ViewGroup,callBack
mViewDragHelper = ViewDragHelper.create(this, new SweepViewCallback());
}
// xml布局加载完成,所有的孩子已经加载完成
@Override
protected void onFinishInflate() {
mContentView = getChildAt(0);
mDeleteView = getChildAt(1);
LayoutParams layoutParams = mContentView.getLayoutParams();
// 拿到layoutParams
mWidth = layoutParams.width;
mHeight = layoutParams.height;
Log.d("ch", "mWidth:" + mWidth);
Log.d("ch", "mHeight:" + mHeight);
LayoutParams layoutParams1 = mDeleteView.getLayoutParams();
mDeleteWidth = layoutParams1.width;
mDeleteHeight = layoutParams1.height;
super.onFinishInflate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 测量孩子的大小
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
Log.d("ch", "width =====" + width);
Log.d("ch", "height =====" + height);
// 期望孩子的大小
mContentView.measure(widthMeasureSpec, heightMeasureSpec);
mDeleteView.measure(MeasureSpec.makeMeasureSpec(mDeleteWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
//设置自己的大小
setMeasuredDimension(width, height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
// 内容部分
int left = 0;
int top = 0;
int right = mContentView.getMeasuredWidth();
int bottom = mContentView.getMeasuredHeight();
Log.d("ch ", "mContentView: " + mContentView.getMeasuredWidth());
mContentView.layout(left, top, right, bottom);
// 删除部分
int left1 = mContentView.getMeasuredWidth();
int top1 = 0;
int right1 = mContentView.getMeasuredWidth() + mDeleteView.getMeasuredWidth();
int bottom1 = mDeleteView.getMeasuredHeight();
Log.d("ch1", "---left1 " + left1 + " ---right" + right1);
mDeleteView.layout(left1, top1, right1, bottom1);
}
// 处理控件的拖动事件
@Override
public boolean onTouchEvent(MotionEvent event) {
// 将onTouchEvent的up move down事件交给ViewDragHelper分析
mViewDragHelper.processTouchEvent(event);
return true;
}
private class SweepViewCallback extends ViewDragHelper.Callback {
// 分析触摸事件
@Override
public boolean tryCaptureView(View child, int pointerId) {
// child为分析的子View,分析的id标记
return child == mContentView || child == mDeleteView;
}
// 分析view的水平拖地
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
// child为触摸的child,left为child的左上角到到直系父容器的左上角的距离
Log.d("ch111","left"+left+mDeleteView.getMeasuredWidth());
//处理边界的问题
if (child == mContentView) {
if (left < -mDeleteView.getMeasuredWidth()) {
left = -mDeleteView.getMeasuredWidth();
}else if (left > 0) {
left = 0;
}
} else if (child == mDeleteView) {
int temp = mContentView.getMeasuredWidth() - mDeleteView.getMeasuredWidth();
if (left < temp) {
left = temp;
} else if (left > mContentView.getMeasuredWidth()) {
left = mContentView.getMeasuredWidth();
}
}
return left;
}
// touchEvent的move事件
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
// ViewCompat.postInvalidateOnAnimation(SweepView.this);
invalidate();
if (changedView == mContentView) {
int l = mContentView.getMeasuredWidth() + left;
int r = mContentView.getMeasuredWidth() + left + mDeleteView.getMeasuredWidth();
int b = mContentView.getMeasuredHeight();
Log.d("ch---", "left " + left);
Log.d("ch ", "l" + l + " r" + r + " b" + b);
mDeleteView.layout(l, 0, r, b);
// 平缓滑动的效果 mViewDragHelper.smoothSlideViewTo(mDeleteView,l,0);
}else if (changedView == mDeleteView) {
int mleft = left - mContentView.getMeasuredWidth();
int mtop = 0;
int mright = left;
int mbottom = mContentView.getMeasuredHeight();
mContentView.layout(mleft,mtop,mright,mbottom);
// mViewDragHelper.smoothSlideViewTo(mContentView,mleft,0);
}
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
public void onViewReleased(View releasedChild, float xvel, float yvel) {
}
}
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
invalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
}
总结
这个效果值做拖地,对于多条消息的滑动打开关闭,删除等效果没有做,实现起来也不难,通过接口回调,即可实现.
在调试的时候如果看不到效果,仔细分析原因,通过打印日志可以很快的找到原因.