Android實現滑動的幾種方法

來源:互聯網
上載者:User

標籤:

下面通過一個例子來總結實現滑動的幾種方式,例子的主要功能就是讓我們的自訂View能夠隨著手指的移動而移動。布局檔案如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.scu.lly.dragviewtest.view.DragView        android:layout_width="100dp"        android:layout_height="100dp" /></LinearLayout>

方式一:layout方法在View進行繪製時,會調用onLayout()方法來設定顯示的位置,因此,我們可以通過修改View的left、top、right、bottom四個屬性來控制View的座標。要控制View隨手指滑動,因此需要在onTouchEvent()事件中進行滑動控制。代碼如下:
public class DragView extends View{    private int mLastX;    private int mLastY;    public DragView(Context context) {        super(context);        init();    }    public DragView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private void init(){        setBackgroundColor(Color.BLUE);    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        int x = (int) ev.getX();        int y = (int) ev.getY();        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                mLastX = x;                mLastY = y;                break;            case MotionEvent.ACTION_MOVE:                int offsetX = x - mLastX;                int offsetY = y - mLastY;                //調整layout的四個座標                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);                break;        }        return true;    }}

方式二:offsetLeftAndRight()和offsetTopAndBottom()這兩個方法其實是對上面那種layout設定方式的封裝、簡化,在layout中,左left、右right兩個方向都是加上offsetX,上top、下bottom兩個方向都是加上offsetY,為了簡化設定四個方向,Android提供了offsetLeftAndRight()來代替左右方向的設定,用offsetTopAndBottom()來代替上下方向的設定。我們只需要修改上面代碼ACTION_MOVE的部分,如下:
<span style="white-space:pre"></span>case MotionEvent.ACTION_MOVE:                int offsetX = x - mLastX;                int offsetY = y - mLastY;                //調整layout的四個座標                //layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);                //使用簡寫形式                offsetLeftAndRight(offsetX);                offsetTopAndBottom(offsetY);                break;

方式三:LayoutParamsLayoutParams儲存了一個View的布局參數,因此我們可以通過動態改變LayoutParams中的布局參數來達到改變View的位置效果。通過getLayoutParams()方法來擷取View的LayoutParams,這裡擷取到的LayoutParams需要根據View所在父布局的類型來設定不同的類型,比如,我們這個自訂View是放在LinearLayout中的,那麼通過getLayoutParams()擷取到的就是LinearLayout.LayoutParams。因此,通過getLayoutParams()擷取到LayoutParams的前提就是這個View需要有一個父布局。同樣,我們只需要修改上面代碼ACTION_MOVE的部分,如下:
case MotionEvent.ACTION_MOVE:    int offsetX = x - mLastX;    int offsetY = y - mLastY;    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();    lp.leftMargin = getLeft() + offsetX;    lp.topMargin = getTop() + offsetY;    setLayoutParams(lp);    break;
可以看到,通過LayoutParams改變一個View的位置時,改變的是這個View的Margin屬性,這也是為什麼這種方式一定要有父布局的原因,只有有了父布局,margin屬性的設定才會起作用。對於使用LayoutParams這種方式改變View位置,如果我們不想考慮父布局的類型,還可以使用ViewGroup.MarginLayoutParams來進行設定,這樣也更加方便。如下:
case MotionEvent.ACTION_MOVE:    int offsetX = x - mLastX;    int offsetY = y - mLastY;    //LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();    ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();    lp.leftMargin = getLeft() + offsetX;    lp.topMargin = getTop() + offsetY;    setLayoutParams(lp);    break;
效果是一樣的。
方式四:scrollTo與scrollBy關於scrollTo()和scrollBy()方法,這篇文章《Scroller大揭秘》中有詳細介紹。
使用scrollTo()和scrollBy()方法需要注意的一點是,scrollTo()和scrollBy()方法移動的是View的content,即讓View的內容移動,如果在ViewGroup中使用scrollTo()和scrollBy()方法,那麼移動的將是所有的子View,如果在View中使用,那麼移動的將是View的內容。例如,TextView,content就是它的文本,ImageView,content就是它的drawable對象。
因此,上面例子中我們如果直接這樣使用:scrollBy(offsetX,offsetY);發現View並沒有移動,但其實是發生了移動的,只不過此時移動的是View中的內容,而我們例子中的content什麼也沒有。所以,我們要想使這個View發生移動,我們就應該在View所在的ViewGroup中使用scrollBy或scrollTo方法來進行移動。同時,使用者兩個方法進行移動的時候,注意此時的座標方向與平常是相反的,具體在《Scroller大揭秘》有講解。代碼如下:
case MotionEvent.ACTION_MOVE:    //int offsetX = x - mLastX;    //int offsetY = y - mLastY;    //此時,計算座標是相反的    int offsetX = mLastX - x;    int offsetY = mLastY - y;    //讓View所在的ViewGroup進行移動    ((View)getParent()).scrollBy(offsetX,offsetY);     break;

方式五:Scroller通過Scroller這個輔助類,配合scrollTo和scrollBy可以實現一些更加進階的滑動效果,關於Scroller類的具體介紹,同樣在這篇文章中有詳解《Scroller大揭秘》。
這裡,我們只是結合上面這個例子實現一個簡單的功能,當我們滑動完畢抬起手指後,View自動回彈到原來的位置。代碼如下:
public class DragView extends View{private int mLastX;    private int mLastY;    private Scroller mScroller;    public DragView(Context context) {        super(context);        init(context);    }    public DragView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    private void init(Context context){        setBackgroundColor(Color.BLUE);        mScroller = new Scroller(context);    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        int x = (int) ev.getX();        int y = (int) ev.getY();        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                mLastX = x;                mLastY = y;                break;            case MotionEvent.ACTION_MOVE:                //int offsetX = x - mLastX;                //int offsetY = y - mLastY;                //此時,計算座標是相反的                int offsetX = mLastX - x;                int offsetY = mLastY - y;                //讓View所在的ViewGroup進行移動                ((View)getParent()).scrollBy(offsetX,offsetY);                break;            case MotionEvent.ACTION_UP:                View viewGroup = (View) getParent();                mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY());                //記住需要invalidate                invalidate();                break;        }    return true;}    @Override    public void computeScroll() {        super.computeScroll();        if(mScroller.computeScrollOffset()){            ((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());        //記住,需要不斷調用invalidate進行重繪        invalidate();        }    }}

以上五種方法就是常用的滑動View的方法。還有兩種方式能夠控制一個View的移動效果:屬性動畫和使用ViewDragHelper,對於這兩種方法,大家可以查閱網上資料,就不詳細介紹了。
(以上內容來源於看《Android群英傳》的總結)


Android實現滑動的幾種方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.