现在微信和QQListView都有一个功能 item滑动出现滑动布局,效果如下:
今天就让我们自个来实现这个效果
一.自定义侧滑菜单:
我们通过分解,知道RecycleView的每个item其实都是一个侧滑菜单 所以我们首先需要实现自定义侧滑菜单,实现效果如下图:
其实实现这个效果也并不难,将其分解我们得出如下实现逻辑:
1.自定义view有两部分组成,主界面和侧滑菜单界面,明显应该继承自ViewGroup;
2.正常情况下侧滑菜单位于主界面右侧,因此我们需要对自定义view的child重写onLayout方法确定其位置
3.实现手势滑动效果,针对这个如果是在以前我们就会通过事件分发机制做一些列的处理。但今天我们使用ViewDragHelper实现这个效果。
废话不多说直接贴出自定义类的代码,然后我们在一步步的分析代码:
SwipeLayout.java
public class SwipeLayout extends FrameLayout{
private ViewDragHelper mDragHelper;//滑动帮助类
private int mScreenWidth;//屏幕宽度
private int mStuate = CLOSE;//当前侧滑菜单状态
private static final int OPEN = 1;
private static final int CLOSE = 2;
public SwipeLayout(Context context) {
super(context);
init(context);
}
public SwipeLayout(Context context, AttributeSet attrs){
super(context, attrs);
init(context);
}
public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
mDragHelper = ViewDragHelper.create(this,1.0f,new ViewDragHelperCallback());
mScreenWidth = getScreenWidth(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b){
super.onLayout(changed, l, t, r, b);
View leftView = getLeftView();
leftView.layout(mScreenWidth,leftView.getTop(),mScreenWidth + leftView.getWidth(),leftView.getBottom());
View mainView = getMainView();
mainView.layout(mainView.getLeft(),mainView.getTop(),mScreenWidth,mainView.getBottom());
}
private class ViewDragHelperCallback extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (child == getMainView()){
if (left > 0) {//左滑动 界面不能滚出屏幕
return 0;
}
if (left > -(getLeftView().getWidth() + getPaddingLeft())){//右划不能超过隐藏布局的宽度
return left;
}
return -getLeftView().getWidth() - getPaddingLeft();
}else{
if (left < mScreenWidth - getLeftView().getWidth() - getPaddingLeft()){
return mScreenWidth - getLeftView().getWidth() - getPaddingLeft();
}
return left;
}
}
@Override
public int getViewHorizontalDragRange(View child) {
return getLeftView().getWidth() + getMainView().getWidth();
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
int left = getPaddingLeft();
if (xvel > 0 || (xvel == 0 && mStuate == OPEN)) {
mStuate = CLOSE;
left = 0;
} else{
mStuate = OPEN;
left -= getLeftView().getWidth();
}
mDragHelper.smoothSlideViewTo(getMainView(),left,releasedChild.getTop());
invalidate();
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
if (changedView == getMainView()){
getLeftView().layout(mScreenWidth + left,getLeftView().getTop(),mScreenWidth + getLeftView().getWidth() + left,getLeftView().getBottom());
}else{
getMainView().offsetLeftAndRight(dx);
}
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
@Override
public void computeScroll()
{
if(mDragHelper.continueSettling(true))
{
ViewCompat.postInvalidateOnAnimation(this);
}
}
private View getMainView(){
if (getChildCount() == 0){
return null;
}
return getChildAt(0);
}
private View getLeftView(){
if (getChildCount() == 0 || getChildCount() ==1){
return null;
}
return getChildAt(getChildCount() - 1);
}
public void open(){
mDragHelper.smoothSlideViewTo(getMainView(),-getLeftView().getWidth()- getPaddingLeft(),getMainView().getTop());
invalidate();
}
public void close(){
mDragHelper.smoothSlideViewTo(getMainView(),-getLeftView().getWidth()- getPaddingLeft(),getMainView().getTop());