效果图:
看网上的都是两个vIEw拼接,默认右侧的不显示,水平移动的时候把右侧的vIEw显示出来。但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高仿的。
知识点:
1、VIEwDragHelper 的用法;
2、滑动冲突的解决;
3、自定义viewgroup。
VIEwDragHelper 出来已经比较久了 相信大家都比较熟悉,不熟悉的话Google一大把这里主要简单用一下它的几个方法
1、tryCaptureVIEw(VIEw child,int pointerID) :确定那个子vIEw可以滑动
2、 getVIEwHorizontalDragRange(VIEw child):用我蹩脚的英语翻译一下是‘返回的是子vIEw在水平方向上可移动的大小,以像素为单位,返回0的时候表示水平方向上不能拖动'
3、clampVIEwpositionHorizontal(VIEw child,int left,int dx):在这里可以对边界进行检查,left和dx分别代表即将移动到的位置
4、onVIEwpositionChanged(VIEw changedVIEw,int top,
int dx,int dy):当要捕获vIEw,由于拖曳或者设定而发生位置变更时回调
它的基本用法是:
public SwipeLayout(Context context,AttributeSet attrs,int defStyle) { super(context,attrs,defStyle); init(); } private voID init() { vIEwDragHelper = VIEwDragHelper.create(this,callback); } public boolean onIntercepttouchEvent(MotionEvent ev) { boolean result = vIEwDragHelper.shouldIntercepttouchEvent(ev); } public boolean ontouchEvent(MotionEvent event) { vIEwDragHelper.processtouchEvent(event); return true; }
1)、在构造方法中创建
2)、在onIntercepttouchEvent 中判断是否拦截
3 )、 在 ontouchEvent出来事件
好了 最不好理解的已经搞定了。接下来看看具体实现:
首先看布局:
<linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:layout_wIDth="match_parent" androID:layout_height="wrap_content" androID:orIEntation="vertical" > <scrollvIEwgroup.lly.com.swiplayout.SwipeLayout androID:ID="@+ID/swipeLayout" androID:layout_wIDth="match_parent" androID:layout_height="wrap_content" > <!-- delete区域的布局 --> <include layout="@layout/layout_delete" /> <!-- item内容的布局 --> <include layout="@layout/layout_content" /> </scrollvIEwgroup.lly.com.swiplayout.SwipeLayout></linearLayout>
这个没什么好说的,一个自定义viewgroup包含两个子控件。
接着看看SwipeLayout是怎么实现的:
@OverrIDe protected voID onFinishInflate() { super.onFinishInflate(); deleteVIEw = getChildAt(0); contentVIEw = getChildAt(1); } @OverrIDe protected voID onSizeChanged(int w,int h,int olDW,int oldh) { super.onSizeChanged(w,h,olDW,oldh); deleteHeight = deleteVIEw.getMeasuredHeight(); deleteWIDth = deleteVIEw.getMeasureDWIDth(); contentWIDth = contentVIEw.getMeasureDWIDth(); screenWIDth = getWIDth(); } @OverrIDe protected voID onLayout(boolean changed,int right,int bottom) { // super.onLayout(changed,left,top,right,bottom); deleteVIEw.layout(screenWIDth - deleteWIDth,(screenWIDth - deleteWIDth) + deleteWIDth,deleteHeight); contentVIEw.layout(0,contentWIDth,deleteHeight); }
上面代码进行了一些初始化的 *** 作,重点看看onlayout里面的,我们继承的是framelayout 这里先画出来 deleteVIEw并让他在右边,然后在上面改了一层contentVIEw,这样显示的时候只会显示contentVIEw。
接下来看ontouch方法
public boolean ontouchEvent(MotionEvent event) { //如果当前有打开的,则下面的逻辑不能执行 if(!SwipeLayoutManager.getInstance().isShouldSwipe(this)){ requestdisallowIntercepttouchEvent(true); return true; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downX = event.getX(); downY = event.getY(); break; case MotionEvent.ACTION_MOVE: //1.获取x和y方向移动的距离 float moveX = event.getX(); float moveY = event.getY(); float delatX = moveX - downX;//x方向移动的距离 float delatY = moveY - downY;//y方向移动的距离 if(Math.abs(delatX)>Math.abs(delatY)){ //表示移动是偏向于水平方向,那么应该SwipeLayout应该处理,请求父vIEw不要拦截 requestdisallowIntercepttouchEvent(true); } //更新downX,downY downX = moveX; downY = moveY; break; case MotionEvent.ACTION_UP: break; } vIEwDragHelper.processtouchEvent(event); return true; }
上面主要就是对事件冲突的处理,当是水平移动的时候就请求父视图不要拦截。
接下来来重点就来了
private VIEwDragHelper.Callback callback = new VIEwDragHelper.Callback() { @OverrIDe public boolean tryCaptureVIEw(VIEw child,int pointerID) { return child==contentVIEw; } @OverrIDe public int getVIEwHorizontalDragRange(VIEw child) { return deleteWIDth; } @OverrIDe public int clampVIEwpositionHorizontal(VIEw child,int dx) { if(child==contentVIEw){ if(left>0)left = 0; if(left<-deleteWIDth)left = -deleteWIDth; } return left; } @OverrIDe public voID onVIEwpositionChanged(VIEw changedVIEw,int dx,int dy) { super.onVIEwpositionChanged(changedVIEw,dx,dy); //判断开和关闭的逻辑 if(contentVIEw.getleft()==0 && currentState!=Swipestate.Close){ //说明应该将state更改为关闭 currentState = Swipestate.Close; //回调接口关闭的方法 if(Listener!=null){ Listener.onClose(getTag()); } //说明当前的SwipeLayout已经关闭,需要让Manager清空一下 SwipeLayoutManager.getInstance().clearCurrentLayout(); }else if (contentVIEw.getleft()==-deleteWIDth && currentState!=Swipestate.Open) { //说明应该将state更改为开 currentState = Swipestate.Open; //回调接口打开的方法 if(Listener!=null){ Listener.onopen(getTag()); } //当前的Swipelayout已经打开,需要让Manager记录一下下 SwipeLayoutManager.getInstance().setSwipeLayout(SwipeLayout.this); } } @OverrIDe public voID onVIEwReleased(VIEw releasedChild,float xvel,float yvel) { super.onVIEwReleased(releasedChild,xvel,yvel); if(contentVIEw.getleft()<-deleteWIDth/2){ //应该打开 open(); }else { //应该关闭 close(); } } };
上面这段代码里面的方法一开始我们都说过了,在来看下在tryCaptureVIEw中我们让 contentVIEw可以滑动,在getVIEwHorizontalDragRange中却东滑动范围是deleteWIDth,在clampVIEwpositionHorizontal中对边界进行了下限制,在onVIEwpositionChanged中进行状态的更新, 最后在手指抬起的时候让vIEw自动回滚,
/** * 打开的方法 */ public voID open() { vIEwDragHelper.smoothSlIDeVIEwTo(contentVIEw,-deleteWIDth,contentVIEw.gettop()); VIEwCompat.postInvalIDateOnAnimation(SwipeLayout.this); } /** * 关闭的方法 */ public voID close() { vIEwDragHelper.smoothSlIDeVIEwTo(contentVIEw,contentVIEw.gettop()); VIEwCompat.postInvalIDateOnAnimation(SwipeLayout.this); }; public voID computeScroll() { if(vIEwDragHelper.continueSettling(true)){ VIEwCompat.postInvalIDateOnAnimation(this); } }
这里注意一定要重写computeScroll方法,不然滑动效果动一下就不动了。
至此这个自定义framelayout就完成了
但是发现一个问题,我们在已经滑动出来的vIEw中上下滑动时,这个vIEw的deleteVIEw还是显示状态,所以还要在activity中处理一下:
recyVIEw.setonScrollListener(new RecyclerVIEw.OnScrollListener() { @OverrIDe public voID onScrollStateChanged(RecyclerVIEw recyclerVIEw,int newState) { super.onScrollStateChanged(recyclerVIEw,newState); } @OverrIDe public voID onScrolled(RecyclerVIEw recyclerVIEw,int dy) { super.onScrolled(recyclerVIEw,dy); if(dy>0 || dy<0){ SwipeLayoutManager.getInstance().closeCurrentLayout(); } } });
当这个RecyclerVIEw是上下滑动时,让子vIEw复位。
收工。
ps:本来是在eclipse中ListvIEw中实现的,但是想想Google都已经不支持eclipse了,而ListvIEw也快被RecyclerVIEw代替了,所以最后还是切换到AndroID studio,用RecyclerVIEw实现了一套。
源码地址
以上所述是小编给大家介绍的AndroID中自定义view实现侧滑效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
总结以上是内存溢出为你收集整理的Android中自定义view实现侧滑效果全部内容,希望文章能够帮你解决Android中自定义view实现侧滑效果所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)