帮我们实现各种类型的复杂手势操作。其实例通过静态工厂创建ViewDragHelper一般用在一个自定义ViewGroup的内部。
初始化操作
private ViewDragHelper mDrragHelper; public SlideViewGroup(@NonNull Context context) { this(context,null); } public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback); }
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);第一个操作表示当前操作的对象,第二个参数为手势操作敏感度,
第三个参数为我们手势处理的毁掉接口
我们需要先在view事件分发时把手势操作交给ViewFragHelper
@Override public boolean onInterceptTouchEvent(MotionEvent event) { //交给viewdrag去拦截 //事件分发拦截 float x=0; int action = event.getAction(); switch(action){ case MotionEvent.ACTION_DOWN: x =event.getX(); break; // return false; case MotionEvent.ACTION_MOVE: if (STATE==0&getX()-x<0){ return mDrragHelper.shouldInterceptTouchEvent(event); }else if (STATE==1){ return mDrragHelper.shouldInterceptTouchEvent(event); } break; } return false; } //boolean control=true;//控制downx的初始化 @Override public boolean onTouchEvent(MotionEvent event) { mDrragHelper.processTouchEvent(event); //if (control) float downX=0; if (event.getAction()==MotionEvent.ACTION_DOWN){ downX=event.getRawX(); if (STATE==1){ //if (event.getRawX()>0&downX<leftWidth-rightViewWidth) //close(); // Toast.makeText(this.getContext(), "leftWidth"+leftWidth+"rawx"+event.getRawX(), Toast.LENGTH_SHORT).show(); } } if (event.getAction()==MotionEvent.ACTION_UP){ //Toast.makeText(this.getContext(), "downx"+downX, Toast.LENGTH_SHORT).show(); //点击删除//&downX>leftWidth-rightViewWidth&downX<leftWidth-rightViewWidth/2 // Toast.makeText(this.getContext(), "删除1", Toast.LENGTH_SHORT).show(); if (STATE==1&event.getRawX()>leftWidth-rightViewWidth&event.getRawX()<leftWidth-rightViewWidth/2){ // Toast.makeText(this.getContext(), "删除2", Toast.LENGTH_SHORT).show(); if (skipListener!=null){ // Toast.makeText(this.getContext(), "删除3", Toast.LENGTH_SHORT).show(); skipListener.onDelete(); } // Toast.makeText(this.getContext(), "删除", Toast.LENGTH_SHORT).show(); } //点击删除&downX>leftWidth-rightViewWidth/2&downX<leftWidth-rightViewWidth if (STATE==1&event.getRawX()>leftWidth-rightViewWidth/2&event.getRawX()<leftWidth){ // Toast.makeText(this.getContext(), "修改", Toast.LENGTH_SHORT).show(); if (skipListener!=null){ skipListener.onDefine(); } } } return true; }
重点在这两句
mDrragHelper.shouldInterceptTouchEvent(event); mDrragHelper.processTouchEvent(event);
我们可以在onInterceptTouchEvent决定什么时候把事件交给我们的手势操作类
然后是回调类
private ViewDragHelper.Callback mCallback=new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(View child, int pointerId) { return child==leftView; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (left>=0) return 0; if (left<-rightViewWidth) return -rightViewWidth; return left; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); rightView.layout(leftWidth + left, 0, leftWidth + rightViewWidth, viewHeight); /* if (left<0&left>rightViewWidth/2){ mDrragHelper.smoothSlideViewTo(leftView,left,0); mDrragHelper.smoothSlideViewTo(rightView,left,0); }*/ /* if (left>=-(leftWidth+rightViewWidth)) { rightView.layout(leftWidth + left, 0, leftWidth + rightViewWidth, viewHeight); } if (left<-(leftWidth+rightViewWidth)){ rightView.layout(leftWidth, 0, leftWidth + rightViewWidth, viewHeight); }*/ } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); Log.i("left xvel",xvel+"y"+yvel); if (xvel<0){ open();/* mDrragHelper.smoothSlideViewTo(rightView,rightViewWidth/2,0);*/ }else if (leftView.getLeft()<-rightViewWidth/2) {open();}else { // Log.i("left open","open"); close(); } } @Override public int getViewHorizontalDragRange(View child) { return -rightViewWidth; } @Override public void onEdgeTouched(int edgeFlags, int pointerId) { super.onEdgeTouched(edgeFlags, pointerId); } };
tryCaptureView的返回值表示我们允许操作的child
clampViewPositionHorizontal()方法的默认返回值为0,返回值代表水平移动的距离,也就是left值,当返回left值时,我们操作的view就会跟着我们的拖动而移动,当然还有数值方向的方法,如果需要也可以重写竖直操作的方法
onViewPositionChanged()方法就是当我们移动时就会回调这个方法,此处的left参数就是水平移动返回的left,dx就是水平距离相对变化
onViewRelased()方法就是手指抬起时(释放)时回调的方法,xvel每秒钟水平速度速度慢时为0,单位为像素,yvel为每秒钟竖直方向的速度。速度有正负之分
滑动边缘:
分为滑动左边缘还是右边缘:EDGE_LEFT和EDGE_RIGHT,下面的代码设置了可以处理滑动左边缘:
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
假如如上设置,onEdgeTouched方法会在左边缘滑动的时候被调用,这种情况下一般都是没有和子view接触的情况。
@Override public void onEdgeTouched(int edgeFlags, int pointerId) { super.onEdgeTouched(edgeFlags, pointerId); Toast.makeText(getContext(), "edgeTouched", Toast.LENGTH_SHORT).show(); }
如果你想在边缘滑动的时候根据滑动距离移动一个子view,可以通过实现onEdgeDragStarted方法,并在onEdgeDragStarted方法中手动指定要移动的子View
@Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { mDragHelper.captureChildView(mDragView2, pointerId); }
滑动
手指在当前view的下边缘就可以滑动
下面看一个我在ontochEvent调用的方法
public void open(){ if (listener!=null){ listener.onOpen(this); } if (mDrragHelper.smoothSlideViewTo(leftView,-rightViewWidth,0)) ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this); STATE=1; }
就是平滑滑动,
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this)
上面那个方法就是刷新布局(重绘操作)
然后会回调次viewgroup的computerScroll
@Override public void computeScroll() { if (mDrragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } }
其实滑动本身还是调用的scrollto跟据时间百分比移动,根据比例移动固定距离后就不移动了,所以我们需要重复刷新,需要判断临界条件,可能是时间可能是距离,可以点进continueSetting方法返回false代表动画完成,进去一看就明白了,需要判断滑动事件是否完成,如果完成就不再刷新,如果没完成就刷新。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍FragmentTabHost使用方法详解,包括了FragmentTabHost使用方法详解的使用技巧和注意事项,需要的朋友参考一下 FragmentTabHost是support-v包下提供的用于集成和管理Fragment页面的组件. 今天要实现的效果图如下: 整体结构是MainActivity+5个模块的Fragment. MainActivity的布局如下: 每个tab的布局如
本文向大家介绍ToolBar使用方法详解,包括了ToolBar使用方法详解的使用技巧和注意事项,需要的朋友参考一下 ToolBar的出现是为了替换之前的ActionBar的各种不灵活使用方式,相反,ToolBar的使用变得非常灵活,因为它可以让我们自由往里面添加子控件.低版本要使用的话,可以添加support-v7包. 今天要实现的效果如下: 由上图可以看到,toolBar的布局还是相对丰富的.要
本文向大家介绍TabLayout使用方法详解,包括了TabLayout使用方法详解的使用技巧和注意事项,需要的朋友参考一下 TabLayout是design库提供的控件,可以方便的使用指示器,功能类似ViewPagerIndicator. 使用非常方便,Android Studio只需要在gradle中引入即可使用 . TabLayout即可以单独使用,也可以配合ViewPager来使用. 先来看
本文向大家介绍jQuery:unbind方法的使用详解,包括了jQuery:unbind方法的使用详解的使用技巧和注意事项,需要的朋友参考一下 jQuery:unbind方法的使用详解 一、前言 unbind方法只能解绑用jQuery的bind方法以及用jquery方法注册的事件处理程序。比如:$(‘a').click(function(){})可以通过unbind解绑。用原生addEventLi
本文向大家介绍Java HttpURLConnection使用方法详解,包括了Java HttpURLConnection使用方法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Java HttpURLConnection使用,供大家参考,具体内容如下 包括使用HttpURLConnection执行get/post请求 GitHub:https://github.com/taz3
本文向大家介绍php使用PDO方法详解,包括了php使用PDO方法详解的使用技巧和注意事项,需要的朋友参考一下 本文详细分析了php使用PDO方法。分享给大家供大家参考。具体分析如下: PDO::exec:返回的是int类型,表示影响结果的条数. 返回的是boolean型,true表示执行成功,false表示执行失败,这两个通常出现在如下代码: 一般情况下可以用$rs0的值判断SQL执行成功与否,
本文向大家介绍Android Tabhost使用方法详解,包括了Android Tabhost使用方法详解的使用技巧和注意事项,需要的朋友参考一下 Android 实现tab视图有2种方法,一种是在布局页面中定义<tabhost>标签,另一种就是继承tabactivity.但是我比较喜欢第二种方式,应为如果页面比较复杂的话你的XML文件会写得比较庞大,用第二种方式XML页面相对要简洁得多。 下面是
本文向大家介绍Hadoop Combiner使用方法详解,包括了Hadoop Combiner使用方法详解的使用技巧和注意事项,需要的朋友参考一下 Hadoop Combiner使用方法详解 Combiner函数是一个可选的中间函数,发生在Map阶段,Mapper执行完成后立即执行。使用Combiner有如下两个优势: Combiner可以用来减少发送到Reducer的数据量,从而提高网络效率。