1. 程式人生 > >實現View 滑動的幾種方法

實現View 滑動的幾種方法

時間過得真快,一轉眼就要到10月了,這幾天風颳的厲害,氣溫驟降,看來秋天真的要來了!

今天我主要是給大家講一些實現View平滑的移動的方法,View 平滑移動的方法一般有一下三種:

1.通過View 本身提供的scrollTo / scrollBy 方法實現滑動

2.通過動畫給View施加平移效果來實現滑動

3.通過改變View 的LayoutParams 使得重新佈局從而實現滑動

1.ScrollTo() / ScrollBy() 方法實現滑動

scrollTo(int destX,int destY) / scrollBy(int deltaX,int deltaY) 這兩個方法是在View 下的,所以android中只要是整合View的皆可使用這種方法實現平滑移動。ScrollTo是基於引數的絕對的滑動,ScrollBy則是相對滑動。在View中原始碼如下:

 public void scrollTo(int x, int y) {
        if (mScrollX != x || mScrollY != y) {
            int oldX = mScrollX;
            int oldY = mScrollY;
            mScrollX = x;
            mScrollY = y;
            invalidateParentCaches();
            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
            if (!awakenScrollBars()) {
                postInvalidateOnAnimation();
            }
        }
    }
 public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }
可以看到ScrollBy 內部呼叫的是ScrollTo方法,由於scrollBy是相對對標,所以需要加上mScrollX 和 mScrollY. 要獲取mScrollX 和 mScrollY 可通過 getScrollX() 和 getScrollY() 實現。那麼什麼是scrollX,scrollY呢? 首先需要明白的一點:ScrollTo / scrollBy 這個兩個方法只是移動View 內部的內容而不是View 本身。舉個例子ScrollView, 當我們在滑動ScrollView的時候ScrollView 本身這個View 並沒有傳送位置或者大小上的任何改變,改變的只是ScrollView 內部的內容區域。
mScrollX 始終等於View的左邊緣 - View的內容區域左邊緣,如果水平從左向右滑動的話mScrollX 為負值,反之為正值 mScrollY 始終等於View的上邊緣 - View的內容區域上邊緣,如果縱向從上向下滑動的話mScrollY為負值,反之為為正值 為了便於理解我花了如下圖,虛線框代表著View 本身,而實體框代表著View 的內容區域,通過該圖應該很快就能理解mScrollX和mScrollY這兩個引數了。
ScrollTo和ScrollBy的使用場景的話,例如我們在使用ScrollView 和 listView 的時候已經滑動到了最底層,那麼想要滑動到最頂層的話直接使用scrollTo(0,0)即可。 需要注意的是:預設ScrollTo這個方式是瞬間滑動到目標位置這樣並不友好,我們可以藉助Scroller 來實現平滑移動。
示例程式碼: 對TextView 進行自定義複寫:
public class MyTextView extends TextView {

    private Scroller mScroller;

    public MyTextView(Context context) {
        this(context, null);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mScroller = new Scroller(context);
    }

    /**
     * 平滑移動到設定的座標
     *
     * @param destX 絕對座標X
     * @param destY 絕對座標Y
     */
    public void smoothScrollTo(int destX, int destY) {
        int mScrollX = getScrollX();
        int mScrollY = getScrollY();

        int deltaX = mScrollX - destX;
        int deltaY = mScrollY - destY;

        if (deltaX == 0 && deltaY == 0)
            return;
        mScroller.startScroll(mScrollX, mScrollY, deltaX, deltaY, 1000);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller != null) {
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                postInvalidate();
            }
        }
    }
}
這樣就可輕鬆的實現平滑移動了,當然加入你使用的是ScrollView 或者是listView這樣的控制元件直接呼叫系統方法:smoothScrollToPosition()即可。當然系統提供的這些平滑移動的方法也是有Scoller實現的,看一下原始碼就知道了。

2 使用動畫實現控制元件的平滑移動    android的動畫包括三大類:幀動畫 補間動畫  屬性動畫  (1) 幀動畫 在anim 資料夾下建立xml檔案,在xml中按照一定的順序將圖片資源 進行排列起來,在佈局中使用 android:background="" 引用即可。示例程式碼如下:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >

    <item
        android:drawable="@drawable/loading1"
        android:duration="200"/>
    <item
        android:drawable="@drawable/loading3"
        android:duration="200"/>
    <item
        android:drawable="@drawable/loading5"
        android:duration="200"/>
    <item
        android:drawable="@drawable/loading7"
        android:duration="200"/>
    <item
        android:drawable="@drawable/loading9"
        android:duration="200"/>
 
</animation-list>
程式碼中的引用:
AnimationDrawable drawable = (AnimationDrawable) mTextView.getBackground();
drawable.start();
drawable.stop();
使用這種動畫方式,應該注意使用圖片較小的資源,不然容易出現oom的異常。 (2)補間動畫   補間動畫包括:TranslateAnimation ScaleAnimation AlphaAnimation RotateAnimation 這種動畫只是一種動畫形式並不能改變控制元件本有的屬性。實現這些效果可以通過程式碼設定也可以通過xml檔案設定。 通過程式碼設定:
TranslateAnimation animation = new TranslateAnimation(0,100,0,100);
animation.setDuration(300);
mTextView.startAnimation(animation);  
通過xml設定:
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator" >

    <alpha
        android:duration="300"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

</set>

Animation utils = AnimationUtils.loadAnimation(this,R.anim.umeng_socialize_fade_in);
mTextView.startAnimation(utils);

(3)屬性動畫 屬性動畫一般常用到的兩個類:ObjectAnimator 和 ValueAnimator(屬性動畫動畫改變的同時,屬性也在進行改變) 程式碼示例:
ObjectAnimator.ofFloat(mTextView,"translationX",0,100).setDuration(300).start();
具體可參照部落格:http://blog.csdn.net/lmj623565791/article/details/38067475 3 通過改變佈局引數的形式 使用佈局引數一般大概步驟如下:比如我想使Button向右平移100px那麼我可以這樣做
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mTextView.getLayoutParams();
params.leftMargin += 100;
mTextView.requestLayout();// 或者 mTextView.setLayoutParams(params);
這個是用場景的話,比如我們要去做,仿QQ那種listView item 優化彈出刪除按鈕的效果,我們就可以使用這種方法,通過不斷的讓刪除Button的佈局寬度變大,你就可以看到那種效果。 以上三種就是目前View 平滑移動的常見方法。