今天就带大家来实现一下简书的滑动返回效果。我们先来看看效果图:最终效果图。gif有点简陋,因为没有具体内容,也没有简书的图片资源。不过还是不妨碍我们的效果展示~OK,接下来的套路,大家可以通过阅读这篇文章来学习:ViewDragHelper的使用(如果你想学习自定义View,那你一定不能错过ViewDragHelper)好像没什么...这个效果不难,会ViewDragHelper的同学10分钟应该能写出来~如果不会也没关系~1.我们自定义一个继承自FrameLayout1.1的SwipeBackFrameLayout,因为黄色的View在left被覆盖了,而另一个View的宽度是MatchParent,所以FrameLayout是一个不错的选择。顺便加个回调,通知activity结束publicvoidsetCallback(CallbackmCallback){this.mCallback=mCallback;}privateCallbackmCallback;publicinterfaceCallback{voidonShouldFinish();}1.2xml布局,很简单:1.3实例化一个ViewDragHelper//1f代表灵敏度mDragHelper=ViewDragHelper.create(this,1f,newViewDragHelper.Callback(){@OverridepublicbooleantryCaptureView(Viewchild,intpointerId){returnfalse;}}//因为我们是从左向右滑动,设置EDGE_LEFTmDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);1.4在SwipeBackFrameLayout中实例化xml中的子ViewInvertedViewmDividerView;vovoteViewmContentViewpro;(){super.onFinishInflate();mDividerView=getChildAt(0);mDividerView.setAlpha(0f);mContentView=getChildAt(1);}1.5让ViewDragHelper处理触摸事件@OverridepublicbooleanonInterceptTouchEvent(MotionEventev){returnmDragHelper.shouldInterceptTouchEvent(ev);}@OverridepublicbooleanonTouchEvent(MotionEventevent){mDragHelper.processTouchEvent(event);returntrue;}1.6重写ViewDragHelper的一些处理方法附了详细注释@OverridepublicvoidonEdintgeToucherlag(super.onEdgeTouched(edgeFlags));//当左边框被触摸时,我们捕获mContentViewmDragHelper.captureChildView(mContentView,pointerId);}@OverridepublicintgetViewHorizo??ntalDragRange(Viewchild){return1;}@OverridepublicvoidonViewPositionChanged(ViewchangedintView,intdleftintdy){super.onViewPositionChanged(changedView,left,top,dx,dy);Log.d(TAG,"onViewPositionChanged()calledwithleft=["+left+"],top=["+top+"],dx=["+dx+"],dy=["+dy+"]");//0.0-1.0//注意这里可以回调一个接口,可以做各种炫酷的效果floatalpha=(float)(left*1.0/mDividerWidth);mDividerView.setAlpha(alpha);}@OverridepublicintclampViewPositionHorizo??ntal(Viewchild,intleft,intdx){//Log.d(TAG,"clampViewPpositionHorizo??ntal()calledwithdx=["+dx+"]");//left的计算我们的目标范围是0-dividerwidth的宽度mLastdx=dx;intnewLeft=Math.min(mDividerWidth,Math.max(left,0));returnnewLeft;}@OverridepublicvoidonViewReleased(ViewreleasedChild,floatxvel,floatyvel){//>0表示用户要关闭if(mLastdx>0){//还不是关闭条件,我们让view滑过去,然后关闭if(mDividerWidth!=releasedChild.getLeft()){mDragHelper.settleCapturedViewAt(mDividerWidth,releasedChild.getTop();invalidate();}else{if(mCallback!=null){mCallback.onShouldFinish();}}}else{//用户不想关闭,则滑动到最左边if(mDividerWidth!=0){mDragHelper.settleCapturedViewAt(0,releasedChild.getTop());invalidate();}}}@OverridepublicvoidonViewDragStateChanged(intstate){super.onViewDragStateChanged(state);//滑动停止,达到滑动判断条件,关闭回调if(mDragHelper.getViewDragState()==ViewDragHelper.STATE_IDLE&&mCallback!=null&&mDividerWidth==mContentView.getLeft()&&mLastdx>0){mCallback.onShouldFinish();}}});1.7增加视图滑动事件的处理。对于上面的mDividerWidth,我们在onLayout中获取privateintmDividerWidth;@OverrideprotectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){super.onLayout(changed,left,top,right,bottom);mDividerWidth=mDividerView.getWidth();}//调用@OverridepublicvoidcomputeScroll时会初始化Noticeview(){super.computeScroll();//Log.d(TAG,"computeScroll()calledwith"+"");if(mDragHelper.continueSettling(true)){invalidate();}}我们写自定义视图后,需要自定义activity的退出动画~2.定义activity的结束动画2.1在anim目录下,创建两个动画xml://no_anim//out_to_right2.2在activity中设置回调监听,使用动画mSwipeBack.setCallback(newSwipeBackFrameLayout.Callback(){@OverridepublicvoidonShouldFinish(){finish();overridePendingTransition(R.anim.no_anim,R.anim.out_to_right);}});好吧!!~代码量很少!~就这么简单~说说吧,简书对代码块的支持太差了,复制的时候代码全乱了!!同学们,我们上源码吧:源码在我的Github上