javaee论坛

普通会员

225648

帖子

98

回复

112

积分

楼主
发表于 2017-09-16 11:07:08 | 查看: 140 | 回复: 2
帮我们实现各种类型的复杂手势操作。其实例通过静态工厂创建
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接触的情况。

@Overridepublic void onEdgeTouched(int edgeFlags, int pointerId) {    super.onEdgeTouched(edgeFlags, pointerId);    Toast.makeText(getContext(), "edgeTouched", Toast.LENGTH_SHORT).show();}

如果你想在边缘滑动的时候根据滑动距离移动一个子view,可以通过实现onEdgeDragStarted方法,并在onEdgeDragStarted方法中手动指定要移动的子View

@Overridepublic 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代表动画完成,进去一看就明白了,需要判断滑动事件是否完成,如果完成就不再刷新,如果没完成就刷新。


普通会员

0

帖子

105

回复

114

积分
沙发
发表于 2019-11-06 02:32:26

楼主节操掉了,还不快捡起来

普通会员

0

帖子

82

回复

88

积分
板凳
发表于 2022-05-11 03:30:54

围观

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017