• android中实现view可以滑动的六种方法续篇(一)


         承接上一篇,如果你没有读过前四章方法,可以点击下面的链接:

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

         下面开始讲第五中方法。

    五、利用Scroller类实现滑动

    (1)基础知识总结

          为了便于下面的阅读代码,先来总结一下关于Scroller类的基础知识。利用Scroller类实现滑动,需要三个步骤:

    步骤一:
    初始化Scroller对象,即mScroller = new Scroller(context)
    步骤二:
    重写computeScroll()方法,实现模拟滑动。可以复制下面的末模板代码:
    public void computeScroll() {
                super.computeScroll();
                
                if(mScroller.computeScrollOffset())
                {
                    ((View)getParent()).scrollTo(mScroller.getCurrX(),
                            mScroller.getCurrY());
                }
                
                invalidate();//必须要调用
            }
    步骤三:
    开启模拟过程,在合适的地方(一般都在move中)startScroll方法。它有两个重载方法如下:
    startScroll(int startX,int startY, int dx,int dy,int duration)
    startScroll(int startX,int startY,int dx,int dy)
    方法中的参数无需多解释了,就是起始坐标与偏移量,还有完成偏移的时间而已。

            需要说明的是:(1)computeScrollOffset方法用来判断是否完成了整个滑动,返回为true,则说明没有完成,否则则完成滑动。

                                (2)getCurrY以及getCurrX获得的是当前的滑动坐标。

                                (3)最后必须要用invalidate方法来刷新。因为computeScroll方法不会自动调用,是在draw方法中被调用的。所以

                                       必须使用invalidate刷新,就会调用draw方法,自然就会调用computeScroll方法了。这样子就会实现循环调用。

                                (4)在startScroll中,偏移量跟使用scrollBy方法中的偏移量用法是一样的,即也必须填写你实际想要移动距离的相

                                       反数。也就是你实际想让它偏移一个正值,这里就填写它相应的负值,如果想偏移一个负值,这里就填写相应的

                                       正值!

    (2)代码实践

           有些东西还是需要在真正的代码中才能说的明白的。我们接着上一篇文章的代码继续编写。为了看清Scroller类是如何实现滑动的,我们

    再次修改DragView的代码。这次修改的有些多。贴完整的代码出来。如下:

     1 package com.example.testdragview;
     2 
     3 import android.content.Context;
     4 import android.util.AttributeSet;
     5 import android.view.MotionEvent;
     6 import android.view.View;
     7 import android.widget.Scroller;
     8 
     9 public class DragView extends View{
    10     
    11     
    12     private int lastX;
    13     private int lastY;
    14     private Scroller mScroller;
    15 
    16     public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
    17         super(context, attrs, defStyleAttr);
    18         
    19         mScroller = new Scroller(context);
    20     }
    21 
    22     public DragView(Context context, AttributeSet attrs) {
    23         super(context, attrs);
    24         mScroller = new Scroller(context);
    25     }
    26 
    27     public DragView(Context context) {
    28         super(context);
    29         mScroller = new Scroller(context);
    30     }
    31 
    32     
    33     
    34     public boolean onTouchEvent(MotionEvent event) {
    35         
    36         //获取到手指处的横坐标和纵坐标
    37         int x = (int) event.getX();
    38         int y = (int) event.getY();
    39         
    40         
    41         switch(event.getAction())
    42         {
    43         case MotionEvent.ACTION_DOWN:
    44             
    45             lastX = x;
    46             lastY = y;
    47             break;
    48             
    49         case MotionEvent.ACTION_MOVE:
    50             
    51             //计算移动的距离
    52             int offX = x - lastX;
    53             int offY = y - lastY;
    54             
    55             View viewGroup = (View) getParent();
    56             
    57             //开启滑动
    58             mScroller.startScroll(viewGroup.getScrollX(),
    59                     viewGroup.getScrollY(), -offX, -offY);
    60         
    61             break;
    62             
    63         case MotionEvent.ACTION_UP:
    64             
    65             break;
    66         }
    67         return true;
    68     }
    69     
    70     
    71     
    72         public void computeScroll() {
    73             super.computeScroll();
    74             
    75             if(mScroller.computeScrollOffset())
    76             {
    77                 ((View)getParent()).scrollTo(mScroller.getCurrX(),
    78                         mScroller.getCurrY());
    79             }
    80             
    81             invalidate();//必须要调用
    82         }
    83 }

         红色部分就是修改的核心代码了。需要说明的是,在开启滑动的代码中,即第58行,使用的是在父视图中使用getScrollX和getScrollY获取

    所滑动到的点的坐标。而getScollX和getScrollY正是从computeScroll中的scrollTo方法中传递过来的。通过阅读源码你可以很清晰的看到这个

    过程。我贴两张源码图吧,如下:

                                   

           上图中观察mScrollX的传递过程,确实如上面我所说的。

           而且在开启滑动的代码中,注意我们将偏移量可是都设定为负值了哦!(正如我上面所讲的设定为相反数即可)。

           好了,关于代码的解释,就讲这么多,其他的都很好理解了。现在就运行程序,效果如下:

         值得注意的是,我们的的DragView(即红色的块块)并不是即时跟随鼠标的滑动,在真机上这个效果将会更加突出!!其实这就是

    Scrollerl类的滑动特点!即手指到达某一位置后,view会随后再平滑的到达这个位置,也就是说并不是view和手指一起到达指定位置的。

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

          因此,一般并不利用Scroller类实现滑动,因为它不是即时的。但却经常用它来实现手指抬起后,view回到初始位置!

          来修改下DragView看看怎么实现这个效果。代码如下:

     1 package com.example.testdragview;
     2 
     3 import android.content.Context;
     4 import android.util.AttributeSet;
     5 import android.view.MotionEvent;
     6 import android.view.View;
     7 import android.widget.Scroller;
     8 
     9 public class DragView extends View{
    10     
    11     
    12     private int lastX;
    13     private int lastY;
    14     private Scroller mScroller;
    15 
    16     public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
    17         super(context, attrs, defStyleAttr);
    18         
    19         mScroller = new Scroller(context);
    20     }
    21 
    22     public DragView(Context context, AttributeSet attrs) {
    23         super(context, attrs);
    24         mScroller = new Scroller(context);
    25     }
    26 
    27     public DragView(Context context) {
    28         super(context);
    29         mScroller = new Scroller(context);
    30     }
    31 
    32     
    33     
    34     public boolean onTouchEvent(MotionEvent event) {
    35         
    36         //获取到手指处的横坐标和纵坐标
    37         int x = (int) event.getX();
    38         int y = (int) event.getY();
    39         
    40         
    41         switch(event.getAction())
    42         {
    43         case MotionEvent.ACTION_DOWN:
    44             
    45             lastX = x;
    46             lastY = y;
    47             break;
    48             
    49         case MotionEvent.ACTION_MOVE:
    50             
    51             //计算移动的距离
    52             int offX = x - lastX;
    53             int offY = y - lastY;
    54             
    55              ((View) getParent()).scrollBy(-offX,- offY);
    56 
    57             break;
    58             
    59         case MotionEvent.ACTION_UP:
    60             
    61             View viewGroup = (View) getParent();
    62             
    63             //开启滑动,让其回到原点
    64             mScroller.startScroll(viewGroup.getScrollX(),
    65                     viewGroup.getScrollY(),
    66                     -viewGroup.getScrollX() ,-viewGroup.getScrollY() );
    67             
    68             break;
    69         }
    70         return true;
    71     }
    72     
    73     
    74     
    75         public void computeScroll() {
    76             super.computeScroll();
    77             
    78             if(mScroller.computeScrollOffset())
    79             {
    80                 ((View)getParent()).scrollTo(mScroller.getCurrX(),
    81                         mScroller.getCurrY());
    82             }
    83             
    84             invalidate();//必须要调用
    85         }
    86 }

          红色部分依旧是修改的核心代码。这里主要就是将实现的滑动效果替换成了用scrollBy来实现即时滑动,然后在手指抬起的up方法中,利用

    Scoller类将view放回原来位置!运行一下,看看效果,如下:

         如上图所示,只要鼠标一抬起,红色块块就会立刻回到原来位置!怎么样不错吧。

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

    好了,关于这个Scroller类的使用,就讲到这里。上面的代码基本都可以当做是模板代码了,需要的时候过来看看复制一下吧。

    未完待续.....(最后一种方法)

  • 相关阅读:
    690. Employee Importance 员工重要性
    682. Baseball Game 棒球比赛计分
    680. Valid Palindrome II 有效的回文2
    553. Optimal Division 最佳分割
    服务器oracle数据库定时备份
    数据类型和抽象数据类型
    静态链表和动态链表的区别:
    it网站
    java 移动开发获取多级下拉框json数据的类和mobile-select-area插件
    redis持久化之aof篇
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4985482.html
Copyright © 2020-2023  润新知