zoukankan      html  css  js  c++  java
  • android中实现view可以滑动的六种方法续篇(二)

          承接上一篇,上一篇中讲解了实现滑动的第五种方法,如果你还没读过,可点击下面链接:

    http://www.cnblogs.com/fuly550871915/p/4985482.html

         这篇文章现在来讲解最后一种方法,也可以说是实现滑动的终极大招!不过相比之前的方法,实现的过程要复杂一些,但是实现的效果当然也会徇丽多彩!

    六、使用ViewDragHelper实现

         (1)基础知识

           使用ViewDragHelper可以实现多种多样的滑动效果,只要细心处理,足够满足你的各种拖动的需求了。下面来讲解一下使用ViewDragHelper的步骤。

    步骤一、实例化

        mViewDragHelper = ViewDragHelper.create(this, callback);

         需要注意的是,ViewDragHelper通常定义在一个ViewGroup中。callback是个回调类,下面自会讲到。

    步骤二、拦截事件

        必须要将触摸事件传递给ViewDragHelper处理。按照下面的模板书写即可。如下:

    public boolean onInterceptTouchEvent(android.view.MotionEvent ev) 
        {
            //注意一定要将触摸事件拦截下来
            return mViewDragHelper.shouldInterceptTouchEvent(ev);
        }
        
        public boolean onTouchEvent(MotionEvent event)
        {
    
            //必须将触摸事件传递给mDragHleper
            mViewDragHelper.processTouchEvent(event);
            
            return true;
        }

     步骤三、重写computeScroll

         其实ViewDragHelper内部也是通过Scroller类实现平滑滑动的,因此它也要重写这个方法。按照下面的模板书写即可:

    public void computeScroll() {
            
            if(mViewDragHelper.continueSettling(true))
            {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }

    步骤四、处理回调的callback

         在回调类ViewDragHelper.Callback中,系统定义了大量的监听方法来帮助我们处理各种事件。

         首先创建这个callback,模板代码如下:

    private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
    //什么时候开始检测触摸事件
    public boolean tryCaptureView(View child, int pointerId) {
    return false;
    }

    }

           下面就开始介绍几个常常被重写的方法

    方法 tryCaptureView
    写法如下:
    //什么时候开始检测触摸事件
            public boolean tryCaptureView(View child, int pointerId) {
                
                return mSecondView == child;
            }
      该方法是告诉回调的callback什么时候开始检测触摸事件。因为ViewDragHelper定义在一个
    ViewGroup中,比如你需要当触摸到第二个子view时,才开始检测触摸事件,就可以如上书写。
    方法 clampViewPositionHorizontal
    写法如下:
    /**
             * 水平方向上的移动,默认的返回值为0,此时将它修改为检测到的left
             */
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                
                return left;
            }
       该方法控制水平方向的移动,默认返回为0,即不移动.如果你想让水平方向上发生移动,可以像上面那样进行书写。
    方法 clampViewPositionVertical
    写法如下:
    /**
             * 垂直方向上的移动,默认值也是0,在这里干脆直接让它返回0
             */
            public int clampViewPositionVertical(View child, int top, int dy) {
                return 0;
            }
    该方法的含义与clampViewPositionHorizontal一样
    方法onViewReleased
    写法如下:
    /**
             * 当手指抬起时或者说是拖动结束时会回调这个方法
             */
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                
            }
    注意:该方法在手指抬起或者说是拖动结束时调用。可以在此方法中写一些你需要处理的逻辑。
    另外还有一些其他方法,介绍如下:
    onViewCaptured() 这个事件在用户触摸到view后回调
    onViewDragStateChanged() 这个事件在拖拽状态改变时回调,比如idle,dragging等状态
    onViewPositionChanged() 这个事件在位置改变时回调,常用于滑动时更改scale进行缩放等效果。

        至此,基本上使用ViewDragHelper进行滑动的方法就讲解完了。但是还要记得在ViewGroup中,要在onFinishInflate方法中将子view获取到。

       另外,ViewDragHelper使用smoothSlideViewTo进行滑动,使用ViewCompat.postInvalidateOnAnmation方法进行刷新。这两个方法一定要同时使用!

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    (2)代码实战

         上面说了那么多,还没实践一下呢!现在就来写一个实际例子,这个例子基本上可以当做模板了,以后想要实现更复杂的功能,可以在此基础上修改。因此,要好好研究这个例子。

         在写代码前先上一张最终的效果图,如下:

           好了,效果很丑陋,但是足够说明问题了。开始看看代码是怎么写的吧。

          新建一个项目。然后自定义一个DragViewGroup继承自ViewGroup,在它的里面使用ViewDragHelper愉快的定制吧。如下:

    package com.example.testdragview;
    
    import android.content.Context;
    import android.support.v4.view.ViewCompat;
    import android.support.v4.widget.ViewDragHelper;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.FrameLayout;
    
    public class DragViewGroup extends FrameLayout{
        
        private ViewDragHelper mViewDragHelper;
        
        private View mFirstView;
        private View mSecondView;
        
        private int mFirstViewWidth;
        
        
    
        public DragViewGroup(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            
            mViewDragHelper = ViewDragHelper.create(this, callback);
        }
    
        public DragViewGroup(Context context, AttributeSet attrs) {
            super(context, attrs);
            mViewDragHelper = ViewDragHelper.create(this, callback);
        }
    
        public DragViewGroup(Context context) {
            super(context);
            mViewDragHelper = ViewDragHelper.create(this, callback);
        }
        
        /**
         * 关于mDragHelper的拖动等操作都在这个类里面操作
         */
        private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
            
            //什么时候开始检测触摸事件
            public boolean tryCaptureView(View child, int pointerId) {
                
                return mSecondView == child;
            }
    
            /**
             * 水平方向上的移动,默认的返回值为0,此时将它修改为检测到的left
             */
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                
                return left;
            }
    
            /**
             * 垂直方向上的移动,默认值也是0,在这里干脆直接让它返回0
             */
            public int clampViewPositionVertical(View child, int top, int dy) {
                return 0;
            }
    
            /**
             * 当手指抬起时或者说是拖动结束时会回调这个方法
             */
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                
                if(mSecondView.getLeft() <100)
                {//如果第二个view的left小于500像素,就不显示第一个view。下面的代码就相当于此
                    
                    mViewDragHelper.smoothSlideViewTo(mSecondView, 0, 0);
                    ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                }else
                {//显示第一个view
                    
                    mViewDragHelper.smoothSlideViewTo(mSecondView, 300, 0);
                    ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                }
                
            }
    
        };
        
        
        /**
         * 布局加载完成后调用
         * 在这个方法里获取子view
         */
        protected void onFinishInflate() {
            super.onFinishInflate();
            
            mFirstView = getChildAt(0);
            mSecondView = getChildAt(1);
        }
        
        /**
         * 子view的大小改变后回调该方法
         * 在这个方法里获取到mFirstView的宽度
         */
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            
            mFirstViewWidth = mFirstView.getMeasuredWidth();
        }
        
    
        public boolean onInterceptTouchEvent(android.view.MotionEvent ev) 
        {
            //注意一定要将触摸事件拦截下来
            return mViewDragHelper.shouldInterceptTouchEvent(ev);
        }
        
        public boolean onTouchEvent(MotionEvent event)
        {
    
            //必须将触摸事件传递给mDragHleper
            mViewDragHelper.processTouchEvent(event);
            
            return true;
        }
        
        public void computeScroll() {
            
            if(mViewDragHelper.continueSettling(true))
            {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
    
    }

          结合前面的基础知识和代码中的注释,应该很好理解了。就是在DragViewGroup里面使用ViewDragHelper定义了一个拖动的效果而已!值得注意的是在onReleased方法中,我们做了这样子的一个设定,即当mSecondView的左边距小于100像素时,就将mSecondView移动到初始位置(造成的效果仍然是遮挡出mFirstView,即关闭mFirstView);当其左边与大于100像素,就将其移动的距离左边300像素的位置(当然是相对于它的ViewGroup的左边距了)。

           下面我们建立建立两个用来填充到DragViewGroup中的布局,分别命名为layout1.xml和layout2.xml。如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center" 
        android:background="#ff0000">
        
        
        <TextView 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="你好啊,我是第一个view"
            android:textSize="30sp"/>
        
    
    </LinearLayout>
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center" 
        android:background="#FFFF80">
        
        
        <TextView 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="拖动我,赶紧拖动我"
            android:textSize="30sp"/>
        
    
    </LinearLayout>

         下面就修改activity_main.xml中的代码,将这两个子布局放进DragViewGroup中吧,如下:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    
        <com.example.testdragview.DragViewGroup
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >
            
            <include layout = "@layout/layout1"/>
            <include layout = "@layout/layout2"/>
            
            
        </com.example.testdragview.DragViewGroup>
            
             
        
    
    </LinearLayout>

           就这样子,所有的工作都完成了,运行程序吧。效果和上面贴出来的图一样。好了,要想掌握好ViewDragHelper,还需要多加练习。

          至此,android中实现view滑动的六种方法都讲完了!

  • 相关阅读:
    我所理解的权限管理系统,纯粹个人规划
    小公司大公司
    找工作神器,提取各大网站有效的招聘信息(前程无忧、智联招聘、猎聘网)
    权限管理系统系列之WCF通信
    权限管理系统系列之序言
    用C#开发的双色球走势图(原创)值得园友拥有(二)接上一篇
    用C#开发的双色球走势图(原创)值得园友拥有
    实例甜点 Unreal Engine 4迷你教程(5)之函数中的静态变量
    实例甜点 Unreal Engine 4迷你教程(4)之用C++实现添加子Widget到VerticalBox中以及ClearChildren
    实例甜点 Unreal Engine 4迷你教程(3)之用C++改变Image小部件的其它属性
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4985867.html
Copyright © 2011-2022 走看看