项目需求想要做一个页面的小挂件,实现类似窗帘的效果,去网上找资料,看到了这个:
Android 窗帘效果
实现的挺好的,但是我们的需求是全屏展开,然后展开后需要通过页面边界触摸关闭。
关于边界的触摸效果想到了官方出了DrawerLayout,它就是通过边界触摸打开一个抽屉效果页面的。
android官方侧滑菜单DrawerLayout详解
看了一会儿源码发现DrawerLayout中实现边界触摸的的部分就是由ViewDragHelper实现的,于是就想自己动手试试。

DEMO

ViewDragHelper的实例创建

mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelperCallBack());mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_BOTTOM);

1.通过工厂模式创建的对象,第一个参数是需要监控的父布局,自定义View中一般就是自己;第二个参数是ViewDragHelper对触摸事件的敏感程度,默认1,越大越敏感;第三个是ViewDragHelper处理触摸事件后的回调。

自定义View的大小和位置控制

重写onMeasure

    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        //frameLayout就按父布局的大小去测绘        measureChild(frameLayout,widthMeasureSpec,heightMeasureSpec);        //绳子按照图片大小从新测量大小        imgWidth=imgRope.getDrawable().getIntrinsicWidth();        imgHeight=imgRope.getDrawable().getIntrinsicHeight();        measureChild(imgRope,MeasureSpec.makeMeasureSpec(imgWidth, MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(imgHeight, MeasureSpec.UNSPECIFIED));    }

重写onLayout

    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        //设置整个控件的高度        MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();        mlp.height = mScreenHeigh + imgWidth;        setLayoutParams(mlp);        //mCurTop是滑动的时候距顶部的距离        frameLayout.layout(0, -mScreenHeigh + mCurTop, mScreenWidth, mCurTop);        imgRope.layout(imgPosX, mCurTop,                imgPosX+imgWidth+imgRope.getPaddingRight()+imgRope.getPaddingRight(),                imgHeight + mCurTop+imgRope.getPaddingBottom()        );}

重写ViewDragHelperCallBack

private class ViewDragHelperCallBack extends ViewDragHelper.Callback {        @Override        public boolean tryCaptureView(View child, int pointerId) {            if(isOpen){//根据是否开关,返回ture则表示可以捕获该view                return child==frameLayout;            }            else{                return child == imgRope;            }        }      //边缘触摸        @Override        public void onEdgeDragStarted(int edgeFlags, int pointerId) {            if(isOpen){                mDragHelper.captureChildView(frameLayout, pointerId);            }            else{                mDragHelper.captureChildView(imgRope, pointerId);            }        }        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            if(child==imgRope){                return imgPosX;            }            return super.clampViewPositionHorizontal(child, left, dx);        }        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            if(child==imgRope) {                return Math.min(Math.max(top, 0), mScreenHeigh);            }            else{                return Math.max(Math.min(top, 0), -mScreenHeigh);            }        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            //手指释放时回调            float movePrecent  = Math.abs(releasedChild.getTop()) / (float) mScreenHeigh;;            int finalTop=0;            if(releasedChild==imgRope) {                finalTop = (yvel >= 100 ||movePrecent > 0.3f) ? mScreenHeigh : 0;                mDragHelper.settleCapturedViewAt(imgPosX, finalTop);            }            else{                finalTop = (Math.abs(yvel)>= 100 || movePrecent > 0.3f) ?-mScreenHeigh:0 ;                mDragHelper.settleCapturedViewAt(0, finalTop);            }            invalidate();        }       //滑动位置变化的时候        @Override        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {            if(changedView==imgRope) {                mCurTop = top;            }            else{                mCurTop=mScreenHeigh+top;            }            requestLayout();        }        @Override        public int getViewVerticalDragRange(View child) {            if (child == imgRope) {                return getMeasuredHeight() - child.getMeasuredHeight();            }            return super.getViewVerticalDragRange(child);        }    }

重写触摸事件

     //触摸区域判断方法    private boolean isTouchPointInView(View view, int x, int y) {        if (view == null) {            return false;        }        int[] location = new int[2];        view.getLocationOnScreen(location);        int left = location[0];        int top = location[1];        int right = left + view.getMeasuredWidth();        int bottom = top + view.getMeasuredHeight();        return y >= top && y <= bottom && x >= left && x <= right;    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        //判断是否是触摸到绳子,如果是绳子,继续拦截触摸事件        if (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) {            imgTouch = isTouchPointInView(imgRope, (int) ev.getX(), (int) ev.getY());        } else {            imgTouch = false;        }             //如果触摸的是绳子或者已经开着了继续拦截触摸事件        if (isOpen || imgTouch) {            return mDragHelper.shouldInterceptTouchEvent(ev);        }        return super.onInterceptTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (isOpen || imgTouch) {            mDragHelper.processTouchEvent(event);            return true;        }        return super.onTouchEvent(event);    }    @Override    public void computeScroll() {        if (mDragHelper.continueSettling(true)) {            invalidate();        }    }

项目地址:链接:http://pan.baidu.com/s/1eRDNYim 密码:e81u

参考:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0911/1680.html
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0925/1713.html

更多相关文章

  1. Android视图控件架构分析之View、ViewGroup
  2. 网络获取图片的方法的重写--较简洁(如果手机缓存里面有就从缓存
  3. android 触摸点在屏幕中的坐标与bitmap在屏幕中坐标的比较
  4. 适用于各种连锁企业15寸多点触摸android收款机消费机pos机
  5. Android(安卓)让人又爱又恨的触摸机制(二)
  6. Android中的WebView的使用
  7. [Android] 滑动操作的原理及处理
  8. android 2.0发布
  9. 多点触摸测试

随机推荐

  1. Android实现底部tabbar按钮突出效果
  2. Android学习经验B
  3. 编程回忆之Android回忆(Android(安卓)Sock
  4. Android(安卓)调用js,传对象到js里面使用a
  5. Android屏幕直播方案
  6. Android(安卓)连接WIF获取的信息剖析
  7. Android.mk语法说明(android ndk开发)
  8. 源码解析Android中的事件处理
  9. Android登录记住密码,AES加密保存密码
  10. 如何在Windows上设置Android环境变量/路