android 平滑切換畫面的幾種方法總結

來源:互聯網
上載者:User

   找了好久才發現的文章

轉自:http://archive.cnblogs.com/a/2265135/ 

第一種: ViewFlipper + GestureDetector;

第二種:自己重寫ViewGroup來管理view;

第三種:利用系統內建的ViewPager。

 

關於第一種方法,很多人用過就只說一下思路:用ViewSwitcher,加上動畫效果就可以做到。

第二種方法參考:http://marshal.easymorse.com/archives/3828,我在這裡就直接貼過來了:

  

       

上述,是手指拖動的效果,如果拖動過螢幕中點,鬆手後就會自動移動到第二屏。另外,如果使用撥動手勢,也可以自動移動下一屏。

 

主要是參考了這個項目:

http://code.google.com/p/andro-views/

有原始碼,不過他的代碼有兩個問題:

  • 有bug,在特定情況下,可能兩屏會同時出現,類似上面第三張圖,不能切換過去,這可能是作者漏掉了一些touch狀態可能性造成的
  • 代碼比較繁雜,作者估計是參考Android原始碼來寫的,有些代碼複製自Android代碼,比如ViewGroup,另外可能參考了ScrollView等

看到eric的實現,讓我明白以前的animation動畫處理以及通過修改空白邊(margin)的方式都不是正道。正道是使用Scroller,這是一個帶動畫支援的滾屏協助類。

使用Scroller的基本思路是,比如在本例中,將多個子視圖(ImageView)橫向排列到布局中(自己實現的布局),然後,通過Scroller可支援類似Windows下捲軸橫向移動的效果,而且是帶動畫的。比如,Scroller的方法:

  • startScroll(int startX, int startY, int dx, int dy),設定x軸和y軸的起點及移動的距離,調用該方法將執行滾動動畫,動畫時間是250毫秒,也可以用重載的另外一個方法,可設定動畫周期
  • abortAnimation(),停止動畫,那麼移動螢幕也會中止,目前我的版本中沒有用到,用的場合是撥動手勢後,又做了按下的手勢
  • computeScrollOffset(),判斷是否移動到指定位置,用於移動過程中調用,如果未到位將繼續移動,產生動畫移動的效果,在本例中,覆蓋ViewGroup的computeScroll方法,在裡面調用了該方法

對Scroller的調用,要在布局(Layout)中進行。

Android中的View有兩個子類,Widget和ViewGroup,Widget是可見的視窗組件,比如按鈕,ViewGroup就是布局,ViewGroup已經提供了多個布局子類,比如LinearLayout等。

本例中實現了自己的ViewGroup子類。

通過覆蓋onLayout方法實現對子視圖的橫向排列布局:

@Override 
protected void onLayout(boolean changed, int left, int top, int right, 
        int bottom) { 
    Log.d(TAG, ">>left: " + left + " top: " + top + " right: " + right 
            + " bottom:" + bottom);

    /** 
     * 設定布局,將子視圖順序橫屏排列 
     */ 
    for (int i = 0; i < getChildCount(); i++) { 
        View child = getChildAt(i); 
        child.setVisibility(View.VISIBLE); 
        child.measure(right – left, bottom – top); 
        child.layout(0 + i * getWidth(), 0, getWidth() + i * getWidth(), 
                getHeight()); 
   

通過覆蓋computeScroll方法,計算移動螢幕的位移和重新繪製螢幕:

@Override 
public void computeScroll() { 
    if (scroller.computeScrollOffset()) { 
        scrollTo(scroller.getCurrX(), 0); 
        postInvalidate(); 
    } 
}

編寫了一個名為scrollToScreen的方法,用於根據指定螢幕號切換到該螢幕:

/** 
* 切換到指定屏 

* @param whichScreen 
*/ 
public void scrollToScreen(int whichScreen) { 
    if (getFocusedChild() != null && whichScreen != currentScreenIndex 
            && getFocusedChild() == getChildAt(currentScreenIndex)) { 
        getFocusedChild().clearFocus(); 
    }

    final int delta = whichScreen * getWidth() – getScrollX(); 
    scroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2); 
    invalidate();

    currentScreenIndex = whichScreen; 
}

snapToDestination方法,是處理當螢幕拖動到一個位置鬆手後的處理:

/** 
* 根據當前x座標位置確定切換到第幾屏 
*/ 
private void snapToDestination() { 
    scrollToScreen((getScrollX() + (getWidth() / 2)) / getWidth()); 
}

 

然後說說手勢事件的處理。eric的實現,全部使用onTouch事件處理,這樣代碼不夠簡明。因為需要記錄很多組合手勢的曆史資料,這樣就必須有一些狀態位,一些座標數值。

我用GestureDetector的手勢處理事件簡化了這方面的處理,只在手勢抬起(UP)事件處理中在ouTouchEvent方法中做了處理。

 

具體代碼見:http://easymorse.googlecode.com/svn/tags/ScrollDemos-0.6/

 

升級版本:

 在此基礎上又實現了個版本,結合了Page Control效果。另外換了個表單視圖,來說明方案的通用性。

      

原始碼見:http://easymorse.googlecode.com/svn/tags/ScrollDemos-0.7/

 

第三種方法:詳見:http://blog.csdn.net/billpig/article/details/6650097

起初最早接觸到左右兩個螢幕切換的是在 《創新源於模仿之三:實現左右兩個螢幕的切換》 這篇文章上,感謝作者為我們提供了這麼好的DEMO。

 

什麼是ViewPager呢?


它是實現左右兩個螢幕平滑地切換的一個類,它是Google提供的,作為Android的一個補充。先上個把,讓大家有個直觀的認識。

 

我們在網上搜尋這相關到主題的時候,會看到有很多關於這方面的問題:如何平滑?水平移動?等等。現在,我們可以自己不去親自做這個費力的事情了,只需要使用到一個叫ViewPager的類即可。ViewPager是最近在Compatibility package發布的,支援android 1.6+,如果要使用的話,要通過SDK Manager去更新Compatibility
package,具體使用方法在<SDK_DOC_PATH>/sdk/compatibility-library.html(SDK_DOC_PATH是內建Android文檔的位置,需要更新到最新的文檔才有)。


《創新源於模仿之三:實現左右兩個螢幕的切換》提供了Workspace實現了左右螢幕的切換,現在Google I/O上已經發布了這樣的Workspace類,方便我們大家去使用,稍後我會同本文DEMO的原始碼一起發布。那ViewPager和Workspace有什麼樣的區別呢?先看下api doc的說法:


Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows.


如上所述,ViewPager提供了一個適配器,方便我們對各個View進行控制,而Workspace需要我們手動去添加,它相當於是一個"靜態切換"。接下來我將介紹下如何使用:

1、下載來Android SDK & AVD manager的更新:Available Packages -> Android Repository -> Android Compatibility Package, revision 3. 它將安裝在\extras\android\compatibility\v4檔案下

2、建立一個Android項目,在上述安裝目錄下把 android-support-v4.jar添加進項目,如果是最新的ADT,只需要右擊project->Android Tools->Add Compatibility Library

3、在Activity中使用ViewPager

4、如果ViewPager是用xml去定義的,需要寫上全域的路徑,如:

  1. <android.support.v4.view.ViewPager  
  2. android:layout_width="match_parent"   
  3. android:layout_height="match_parent"   
  4. android:id="@+id/awesomepager"/>


5、建立一個PagerAdapter,實現如下方法:

 getCount(), instantiateItem(), destroyItem(), isViewFromObject() 。 

總上所述,貼上俺的代碼,我們發現,可以很快很簡單的實現左右兩個螢幕的切換 

   

  1. public class AwesomePagerActivity extends Activity {  
  2.       
  3.     private ViewPager awesomePager;  
  4.   
  5.     private Context cxt;  
  6.     private AwesomePagerAdapter awesomeAdapter;  
  7.       
  8.     private LayoutInflater mInflater;  
  9.     private List<View> mListViews;  
  10.       
  11.     /** Called when the activity is first created. */  
  12.     @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.         cxt = this;  
  17.           
  18.         awesomeAdapter = new AwesomePagerAdapter();  
  19.         awesomePager = (ViewPager) findViewById(R.id.awesomepager);  
  20.         awesomePager.setAdapter(awesomeAdapter);  
  21.           
  22.         mListViews = new ArrayList<View>();  
  23.         mInflater = getLayoutInflater();  
  24.         mListViews.add(mInflater.inflate(R.layout.layout1, null));  
  25.         mListViews.add(mInflater.inflate(R.layout.layout2, null));  
  26.         mListViews.add(mInflater.inflate(R.layout.layout3, null));  
  27.           
  28.     }  
  29.       
  30.     private class AwesomePagerAdapter extends PagerAdapter{  
  31.   
  32.           
  33.         @Override  
  34.         public int getCount() {  
  35.             return mListViews.size();  
  36.         }  
  37.   
  38.         /** 
  39.          * 從指定的position建立page 
  40.          * 
  41.          * @param container ViewPager容器 
  42.          * @param position The page position to be instantiated. 
  43.          * @return 返回指定position的page,這裡不需要是一個view,也可以是其他的視圖容器. 
  44.          */  
  45.         @Override  
  46.         public Object instantiateItem(View collection, int position) {  
  47.   
  48.               
  49.             ((ViewPager) collection).addView(mListViews.get(position),0);  
  50.               
  51.             return mListViews.get(position);  
  52.         }  
  53.   
  54.         /** 
  55.          * <span >從指定的position銷毀page</span> 
  56.          *  
  57.          *  
  58.          *<span >參數同上</span> 
  59.          */  
  60.         @Override  
  61.         public void destroyItem(View collection, int position, Object view) {  
  62.             ((ViewPager) collection).removeView(mListViews.get(position));  
  63.         }  
  64.   
  65.           
  66.           
  67.         @Override  
  68.         public boolean isViewFromObject(View view, Object object) {  
  69.             return view==(object);  
  70.         }  
  71.   
  72.         @Override  
  73.         public void finishUpdate(View arg0) {}  
  74.           
  75.   
  76.         @Override  
  77.         public void restoreState(Parcelable arg0, ClassLoader arg1) {}  
  78.   
  79.         @Override  
  80.         public Parcelable saveState() {  
  81.             return null;  
  82.         }  
  83.   
  84.         @Override  
  85.         public void startUpdate(View arg0) {}  
  86.           
  87.     }  
  88.       
  89.       
  90. }  

就這樣,我們可以很容易就實現左右兩個螢幕之間的切換。具體頁面到內容就靠大家去發揮了!

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.