在這篇文章中,我們將介紹SwipeRefreshLayout元件。這個元件被使用時使用者可以使用掃動手勢重新整理UI。在以前的文章中,我們談到了另一種方法來重新整理,我們叫搖晃重新整理介面,在這裡使用者搖晃智慧手機,使用加速度感測器的應用程式重新整理使用者介面。我們在這篇文章中,主要介紹自定義實現此重新整理模式。
SwipeRefreshLayout元件是由SDK提供,已經被用於一些Android自己的應用程式(比如Gmail)的實現。
簡介
SwipeRefreshLayout元件只接受一個子元件:即需要重新整理的那個元件。它使用一個偵聽機制來通知擁有該元件的監聽器有重新整理事件發生,換句話說我們的Activity必須實現通知的介面。該Activity負責處理事件重新整理和重新整理相應的檢視。一旦監聽者接收到該事件,就決定了重新整理過程中應處理的地方。如果要展示一個“重新整理動畫”,它必須呼叫setRefrshing(true)
,否則取消動畫就呼叫setRefreshing(false)
。
怎樣使用SwipeRefreshLayout
現在我們知道這元件如何工作的,我們將建立一個簡單的例子來說明如何使用。假設使用者通過使用一個垂直滑動手勢來產生一個隨機數:
通常來說這是根元件:
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 35 36 37 38 39 40 41 42 43 44 |
; html-script: false ] <android.support.v4.widget.SwipeRefreshLayout android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:id="@+id/swipe"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Random number:" android:id="@+id/lbl"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/rndNum" android:layout_toRightOf="@id/lbl"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/lbl" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:text="Swipe to Refresh" style="@android:style/TextAppearance.Medium"/> </RelativeLayout> </ScrollView> </android.support.v4.widget.SwipeRefreshLayout> |
從上面佈局來看,SwipeRefreshLayout只有一個子元件。現在我們來編寫Activity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
; html-script: false ] @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe); final TextView rndNum = (TextView) findViewById(R.id.rndNum); swipeView.setColorScheme(android.R.color.holo_blue_dark, android.R.color.holo_blue_light, android.R.color.holo_green_light, android.R.color.holo_green_light); swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { swipeView.setRefreshing(true); Log.d("Swipe", "Refreshing Number"); ( new Handler()).postDelayed(new Runnable() { @Override public void run() { swipeView.setRefreshing(false); double f = Math.random(); rndNum.setText(String.valueOf(f)); } }, 3000); } }); } |
正如你在示例中所看到的,事件發生在onCreate
方法。在第6行,我們得到SwipeRefreshLayout引用,這樣我們就可以設定監聽器(10、11、12行)。在監聽者這邊,我們通過設定setRefreshing(true)
動開啟重新整理畫,然後生成隨機數。在結束的時候(這裡模擬了一個相當漫長的過程)停止動畫。
在ListView上使用SwipeRefreshLayout
另一個有趣的例子是在ListView中如何使用SwipeRefreshLayout。這是一個有趣的例子,因為在真正的應用程式中,我們經常會遇到這種情況。我們有一些帶ListView的專案,希望對它們重新整理。如果ListView是SwipeRefreshLayout唯一的孩子,不會出現任何問題,一切都會執行正常。在某些情況下,不僅有ListView可能還有其他的元素。假設有這樣一個介面:
這種情況有些複雜,如果我們向上滾動在ListView中專案,一切都如預期那樣顯示。但如果向下滾動,重新整理過程開始列表項並不滾動。在這種情況下,我們可以使用一個小技巧,可以通過setEnabled(false)
禁止使用重新整理通知,當Listview中第一個項可見時而再啟用它:
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 35 36 37 38 39 40 41 |
; html-script: false ] @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe); swipeView.setEnabled(false); ListView lView = (ListView) findViewById(R.id.list); ArrayAdapter adp = new ArrayAdapter(this, android.R.layout.simple_list_item_1, createItems(40,0 )); lView.setAdapter(adp); swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { swipeView.setRefreshing(true); ( new Handler()).postDelayed(new Runnable() { @Override public void run() { swipeView.setRefreshing(false); } }, 3000); } }); lView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView absListView, int i) { } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem == 0) swipeView.setEnabled(true); else swipeView.setEnabled(false); } }); } |
正如第33行public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount)
看到的,我們重寫了ListView中的onScrollListener去處理啟用/禁用機制。