View绘制1-工具类

绘制工具类

Configuration Context配置

描述的是设备的配置信息
获取像素密度、横竖屏、键盘信息、字体缩放等级等等信息

    private void getConfig() {
        StringBuilder sb = new StringBuilder();
        Configuration conf = context.getResources().getConfiguration();
        if (conf.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // 横屏
            sb.append("横屏\n");
        } else if (conf.orientation == Configuration.ORIENTATION_PORTRAIT) {
            // 竖屏
            sb.append("竖屏\n");
        }
        // 字体缩放级别
        sb.append("frontScale:" + conf.fontScale + "\n");
        sb.append("像素密度:" + conf.densityDpi + "\n");
        sb.append("键盘:"
                + (conf.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO ? "划出"
                        : "隐藏"));
        tvHello.setText(sb.toString());
    }

ViewConfiguration View配置

获取视图操作常用配置信息
如判定双击时间间隔判定,长按时间间隔判定,滑动距离判定,滑动距离、速度

    private void getViewConfig() {
        StringBuilder sb = new StringBuilder();
        ViewConfiguration vConf = ViewConfiguration.get(context);
        sb.append("双击间隔时间:" + vConf.getDoubleTapTimeout() + "\n");
        sb.append("长按时间:" + vConf.getLongPressTimeout() + "\n");
        sb.append("Fling速度最小值:" + vConf.getScaledMinimumFlingVelocity() + "\n");
        sb.append("Fling速度最大值:" + vConf.getScaledMaximumFlingVelocity() + "\n");
        sb.append("Fling滑动距离:" + vConf.getScaledOverflingDistance() + "\n");
        sb.append("判定滑动的距离:" + vConf.getScaledTouchSlop() + "\n");
        tvHello.setText(sb.toString());
    }

GestureDecetor 手势监听器

GestureDetector.OnGestureListener 监听接口

  1. 实现监听器OnGestureListener
    class GestureImpl implements GestureDetector.OnGestureListener {

        @Override
        public boolean onDown(MotionEvent e) {
            // 触碰到屏幕
            return false;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            // 按下未松开

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            // 轻击屏幕
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            // 滑动 无论滑动速率快慢都会触发
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            // 长按

        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            /*
             * 滑动 和onScroll相比此方法对滑动的速率有一定的要求
             * 速率大小从ViewConfiguration的getScaledMinimumFlingVelocity(),
             * getScaledMaximumFlingVelocity()获取
             */
            return false;
        }
    }

2.生成GestureDecetor对象

    private GestureDetector mGDetector;

    public MyView(Context context) {
        super(context);
        mGDetector = new GestureDetector(getContext(), new GestureImpl());
    }

3.事件转发
例如View的onTouch事件

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mGDetector.onTouchEvent(event);
    }

GestureDetector.SimpleGestureListenter 简单监听类,实现了常用方法

VolecityTracker 速率跟踪器

  1. 创建VolecityTracker对象
    private void startVelocityTracker(MotionEvent event) {
        if (vTracker == null) {
            vTracker = VelocityTracker.obtain();
        }
        vTracker.addMovement(event);
    }

2.追踪事件

    private int getScrollTrakcer() {
        //1000ms内的变化
        vTracker.computeCurrentVelocity(1000);
        //X轴的变化
        int velocity = (int) vTracker.getXVelocity();
        return Math.abs(velocity);
    }

3.回收资源

    private void stopVelocityTracker() {
        if (vTracker != null) {
            vTracker.recycle();
            vTracker = null;
        }
    }

Scroller-可视区域

内容移动、背景不变

scroll改变的是View填充的内容,view所处的位置和背景是不变的。
这里写图片描述
阴影部分表示内容

反笛卡尔坐标系

Scroll的坐标系刚好和笛卡尔坐标系相反,以左上角为坐标原点(0,0)
这里写图片描述
这里写图片描述
也就相当于Android-Scroll坐标系的(-100,-100) 等价于 笛卡尔坐标系的(100,100)

scrollTo & scrollBy

scrollBy 其实调用的是scrollTo的方法

public void scrollBy(int x, int y) {   
       scrollTo(mScrollX + x, mScrollY + y);   
} 

只是scrollBy会保留上次的移动位置

ViewDragHelper 视图拖动

Android的侧滑菜单,在DrawerLayout出现之前,侧滑菜单都是由第三方开源代码实现的,其中著名的当属 MenuDrawer ,MenuDrawer重写onTouchEvent方法来实现侧滑效果,代码量很大,实现逻辑也需要很大的耐心才能看懂。为了解拖动手势分析过于复杂,Google提出了ViewDragHelper,其作用和GrestureDecetor类似,简化操作。
我们来一步一步的创建一个ViewDragHelper。

初始化

ViewDragHelper一般用在一个自定义ViewGroup的内部。

    private final ViewDragHelper mDragHelper;
    void init(){
        mDragHelper = ViewDragHelper.create(this, 1f, new DragHelperCallback());
    }

其中
第一个参数为this,表示该类生成的对象,他是ViewDragHelper的拖动处理对象,必须为ViewGroup,因为拖动的是子View他必定存在于一个ViewGrounp中。
第二个参数表示敏感度,数值越高越敏感;
第三个参数是拖动回调,需要自己实现

拖动行为的处理 实现ViewDragHelper.DragHelperCallback

重要方法:

  1. public boolean tryCaptureView(View child, int pointerId) 选择要拖动的对象
  2. public int clampViewPositionHorizontal(View child, int left, int dx)水平方向越界处理
  3. public boolean onInterceptTouchEvent(MotionEvent ev)垂直方向越界处理
  4. public boolean onInterceptTouchEvent(MotionEvent ev)拖动事件结束
  5. public void onEdgeDragStarted(int edgeFlags, int pointerId)边缘拖动可用

实现代码

1.水平拖动


        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            if (mDragHorizontal || mDragCapture || mDragEdge) {
                final int leftBound = getPaddingLeft();
                final int rightBound = getWidth() - mDragView1.getWidth();

                final int newLeft = Math.min(Math.max(left, leftBound),
                        rightBound);

                return newLeft;
            }
            return super.clampViewPositionHorizontal(child, left, dx);
        }

第二个参数left表示拖动的具体位置返回,一般我们不需要处理它,但是这里需要让view滑动的范围处于x轴的(leftPadding,getWidth()-view.width)之间,就需要做一些判断
这里写图片描述
2.垂直拖动

        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            if (mDragVertical) {
                final int topBound = getPaddingTop();
                final int bottomBound = getHeight() - mDragView1.getHeight();
                // Math.max(top, topBound) 上边界的最小值,让子view不能在上方滑出视图
                // Math.min 下边界 让子view不能从下方滑出视图
                final int newTop = Math.min(Math.max(top, topBound),
                        bottomBound);

                return newTop;
            }
            return super.clampViewPositionVertical(child, top, dy);
        }

这里写图片描述
3.边缘拖动

    @Override
    public void onEdgeDragStarted(int edgeFlags, int pointerId) {
            // 不用接触拖动view直接接触边缘即可拖动
            if (mDragEdge) {
                mDragHelper.captureChildView(mDragView1, pointerId);
            }
    }

    public void setDragEdge(boolean dragEdge) {
        // 设置左边缘
        mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
        mDragEdge = dragEdge;
    }

这里写图片描述
4.其他处理事件

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // 拖动结束
        final int action = MotionEventCompat.getActionMasked(ev);
        if (action == MotionEvent.ACTION_CANCEL
                || action == MotionEvent.ACTION_UP) {
            mDragHelper.cancel();
            return false;
        }
        return mDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // 拖动开始
        mDragHelper.processTouchEvent(ev);
        return true;
    }

参考:http://blog.csdn.net/lfdfhl/article/details/51324275

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值