實現Material風格的滑動刷新Swipe to Refresh

Material Design用戶界面指南中很是棒的一個設計是Swipe to Refresh UI pattern。實際上你可能已經看到或者用過這種效果了。在不少熱門的app中都有這種效果,比facebok、 Google Newsstand, Trello, Gmail等等。html

相似於以下效果:
android

cat names gif

Swipe to Refresh UI很是適合於基於adapter的控件(如RecyclerView and ListView),通常它們都須要支持用戶的刷新請求。關於Swipe to Refresh的 實現,在KitKat版本中就有了SwipeRefreshLayout,Lollipop中對SwipeRefreshLayout作了改進,v4包含 了SwipeRefreshLayout控件,咱們只需作一些設置就能夠了。爲了方便讀者,我把demo放在了github 上 下載地址git

咱們是在一個包含最新版本Support庫的Android Studio項目中實現Swipe to Refresh,咱們要作的第一件事就是將support library添加進build.gradlegithub

1
compile 'com.android.support:support-v4:21.0.+'

在新建工程嚮導的時候自動建立了res/layouts/activity_main.xml文件,咱們將一個ListView添加進SwipeRefreshLayout控件web

1
2
3
4
5
6
7
8
9
10
11
<android.support.v4.widget.SwipeRefreshLayout
         android:id= "@+id/activity_main_swipe_refresh_layout"
         android:layout_width= "match_parent"
         android:layout_height= "wrap_content" >
         <ListView
             android:id= "@+id/activity_main_listview"
             android:layout_width= "match_parent"
             android:layout_height= "match_parent"
             >
         </ListView>
     </android.support.v4.widget.SwipeRefreshLayout>

注 意ListView被包含在了SwipeRefreshLayout的裏面。每次咱們滑動ListView到SwipeRefreshLayout邊緣的 時候,SwipeRefreshLayout都會顯示一個正在加載的圖標,同時觸發一個onRefresh事件。onRefresh是咱們爲本身list 刷新數據添加的一個回調方法。api


設置adapter
app

佈局咱們已經搞定,如今爲列表添加數據,咱們用一個簡單的adapter來顯示數據,數據來自於res/strings.xml文件:dom

1
2
3
4
5
6
7
8
9
10
11
<string-array name= "cat_names" >
     <item>George</item>
     <item>Zubin</item>
     <item>Carlos</item>
     <item>Frank</item>
     <item>Charles</item>
     <item>Simon</item>
     <item>Fezra</item>
     <item>Henry</item>
     <item>Schuster</item>
</string-array>

設置adapter:async

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MainActivity extends Activity {
   ListView mListView;
   SwipeRefreshLayout mSwipeRefreshLayout;
   Adapter mAdapter;
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super .onCreate(savedInstanceState);
     setContentView(R.layout.acivity_main);
     SwipeRefreshLayout mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.activity_main_swipe_refresh_layout);
     mListView = findViewById(R.id.activity_main_list_view);
  mListView.setAdapter( new ArrayAdapter<String>(){
     String[] fakeTweets = getResources().getStringArray(R.array.fake_tweets);
     mAdapter = new ArrayAdapter<String>( this , android.R.layout.simple_list_item_1, fakeTweets)
     listView.setAdapter(mAdapter);
   });
   }
}



處理數據刷新
ide

adapter 已經設置,如今咱們添加下拉刷新事件。咱們會免費得到一個動畫效果的加載圖標,咱們只須要決定ListView該作什麼,這取決於 SwipeRefreshLayout的OnRefreshListener 接口是如何實現的。咱們用getNewCatNames模擬從webservice 中獲得新數據。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Override
   public void onCreate(Bundle savedInstanceState) {
   ...
     listView.setAdapter();
     mSwipeRefreshLayout.setOnRefreshListener( new SwipeRefreshLayout.OnRefreshListener() {
       @Override
       public void onRefresh() {
             refreshContent();
           ...
   }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
   // fake a network operation's delayed response
   // this is just for demonstration, not real code!
   private void refreshContent(){
   new Handler().postDelayed( new Runnable() {
           @Override
           public void run() {
     mAdapter = new ArrayAdapter<String>(MainActivity. this , android.R.layout.simple_list_item_1, getNewCatNames());
     mListView.setAdapter(mAdapter);
     mSwipeRefreshLayout.setRefreshing( false );
   });
   }
   // get new cat names.
   // Normally this would be a call to a webservice using async task,
   // or a database operation
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
  private List<String> getNewCatNames() {
         List<String> newCatNames = new ArrayList<String>();
         for (int i = 0; i < mCatNames.size(); i++) {
           int randomCatNameIndex = new Random().nextInt(mCatNames.size() - 1);
           newCatNames.add(mCatNames.get(randomCatNameIndex));
         }
         return newCatNames;
     }


注意上面的代碼中refreshContent()方法最後一行代碼setRefreshing(false);setRefreshing的做用是設置刷新加載效果的icon是否繼續顯示,這裏使用handler作了個延時,模擬實際加載數據須要的時間,當handler的post開始執行的時候setRefreshing(false)表示加載結束,中止播放加載動畫。


自定義

你能夠自定義SwipeRefreshLayout的外觀。setColorSchemeResources()能夠改變加載圖標的顏色。

先在資源文件中定義幾個顏色值:

1
2
3
4
5
<resources>
     <color name= "orange" > #FF9900</color>
   <color name= "green" > #009900</color>
     <color name= "blue" > #000099</color>
</resources>


而後調用setColorSchemeResources(R.color.orange, R.color.green, R.color.blue);

cat names color

SwipeRefreshLayout旋轉的時候將會在這三種顏色間切換。

就如你所看到的Swipe to Refresh簡化了用戶請求更新數據的操做,關於SwipeRefreshLayout的更多api請查看官方文檔


注:本篇文章提供的demo編譯的時候雖然用的是21版本的appcompat,可是運行仍是須要在5.0的設備上,由於demo的Material主題和顏色appcompat無能爲力。固然你能夠以下更改一下主題,這樣在4.x版本上也能運行:

demo原本的主題:

styles.xml

1
2
3
4
5
6
7
<resources>
     <!-- Base application theme. -->
     <style name= "AppTheme" parent= "android:ThemeOverlay.Material.Light" >
         <!-- Customize your theme here. -->
         <item name= "android:colorPrimary" >@android:color/holo_blue_dark</item>
     </style>
</resources>

改爲:

1
2
3
4
5
6
7
<resources>
     <!-- Base application theme. -->
     <style name= "AppTheme" parent= "Theme.AppCompat.Light" >
         <!-- Customize your theme here. -->
                                                  
     </style>
</resources>



http://design.1sters.com/

相關文章
相關標籤/搜索