Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發筆記(一百二十三)下拉刷新布局SwipeRefreshLayout

Android開發筆記(一百二十三)下拉刷新布局SwipeRefreshLayout

編輯:關於Android編程

SwipeRefreshLayout

下拉刷新布局SwipeRefreshLayout是Android又一與時俱進的控件,顧名思義它隨著用戶手勢向下滑動就會觸發刷新操作。從實際的下拉效果來看,SwipeRefreshLayout秉承了Android一貫的簡潔界面,可定制性並不太好,遠不如開源的下拉刷新框架PullToRefresh,但畢竟是原生的控件,用起來比較方便,所以我們還是好好了解了解它。
SwipeRefreshLayout最早在19.1的support-v4庫中引入,所以要先確保sdk的“Android Support Library”版本不低於19.1。另外,SwipeRefreshLayout的源碼多次升級,因此有新版與舊版之分,兩版之間不但支持的方法有區別,而且界面效果也有差異。


下面是SwipeRefreshLayout的常用方法說明:
setColorScheme : 設置進度條/圓圈的顏色。(該方法在新版中已被廢棄)
setOnRefreshListener : 設置刷新監聽器。在下拉松開時觸發該監聽器,需要重寫該監聽器的onRefresh方法。
setRefreshing : 設置刷新的狀態。true表示正在刷新,false表示結束刷新。
isRefreshing : 判斷是否正在刷新。
下面是新版增加的方法說明:
setColorSchemeColors : 設置進度圓圈的圓環顏色。
setProgressBackgroundColorSchemeColor : 設置進度圓圈的背景顏色。
setProgressViewOffset : 設置進度圓圈的偏移量。第一個參數表示進度圈是否縮放,第二個參數表示進度圈開始出現時距頂端的偏移,第三個參數表示進度圈拉到最大時距頂端的偏移。
setDistanceToTriggerSync : 設置手勢向下滑動多少距離才會觸發刷新操作。


SwipeRefreshLayout的舊版與新版之間的界面區別主要有:
1、舊版的進度條是布局頂部的一條橫線,而新版的布局頂部的一個圓圈。
2、舊版在下拉時,進度條不動,頁面會隨著向下滑動;而新版在下拉時,頁面不再向下滑動,進度圓圈會向下滑動。
這兩種顯示效果各有千秋,開發者可按照個人喜好決定采用哪種效果。需要注意的是,想要舊版的效果,就得使用舊版的android-support-v4.jar;想要新版的效果,就得使用新版的android-support-v4.jar。新舊兩版的v4包見本文末尾的代碼工程。


下面是舊版SwipeRefreshLayout的下拉刷新效果截圖:
\


下面是新版SwipeRefreshLayout的下拉刷新效果截圖:
\


下面是簡單下拉刷新的示例代碼(新舊版通用,只需更換v4包即可):
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.widget.TextView;

public class SimpleActivity extends Activity implements OnRefreshListener {
	
	private TextView tv_simple;
	private SwipeRefreshLayout srl_simple;

	private Handler mHandler = new Handler();

	@SuppressLint("ResourceAsColor")
	@SuppressWarnings("deprecation")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_simple);

		tv_simple = (TextView) findViewById(R.id.tv_simple);
		srl_simple = (SwipeRefreshLayout) findViewById(R.id.srl_simple);
		srl_simple.setOnRefreshListener(this);
		//舊版用下面的setColorScheme設置進度條顏色
		srl_simple.setColorScheme(R.color.red, R.color.orange, R.color.green, R.color.blue);
		//新版用下面的setColorSchemeResources設置進度圓圈顏色
//		srl_simple.setColorSchemeResources(
//				R.color.red, R.color.orange, R.color.green, R.color.blue );
		//舊版v4包中無下面三個方法
//		srl_simple.setProgressBackgroundColorSchemeResource(R.color.black);
//		srl_simple.setProgressViewOffset(true, 0, 50);
//		srl_simple.setDistanceToTriggerSync(100);
	}

	@Override
	public void onRefresh() {
		tv_simple.setText("正在刷新");
		mHandler.postDelayed(mRefresh, 3000);
	}
	
	private Runnable mRefresh = new Runnable() {

		@Override
		public void run() {
			tv_simple.setText("刷新完成");
			srl_simple.setRefreshing(false);
		}
		
	};
	
}


SwipeRefreshLayout+ListView下拉刷新

SwipeRefreshLayout搭配ListView可實現簡單的列表數據下拉刷新。


首先要注意:在布局文件中,android.support.v4.widget.SwipeRefreshLayout下面只能有一個直接子視圖,如果有多個子視圖,那麼將只展示第一個子視圖,後面的子視圖將不予展示。如下面這種寫法,只會展示名為tv_listview的TextView數據,而不會展示名為lv_content的ListView數據。


    
        
        
            
        

    



下面這個才是正確的寫法:


    

        

            

            
        
    



SwipeRefreshLayout自帶的刷新提示只有一個進度圓圈,顯然不能滿足多變的定制化需求,比如我們常常需要展示不同的提示文本和提示圖片,這時就要在ListView控件上面增加一塊提示區域,用來存放個性化的提示內容。這裡我們先在提示區域放置一個TextView控件,用來展示最基本的提示文字,在刷新開始時顯示該提示,刷新結束時移除該提示。


下面是SwipeRefreshLayout+ListView的下拉刷新效果截圖:
\


下面是SwipeRefreshLayout+ListView的頁面代碼示例:
import com.example.exmswipe.adapter.TitleListAdapter;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;

public class ListviewActivity extends Activity implements OnRefreshListener {
	
	private TextView tv_listview;
	private SwipeRefreshLayout srl_listview;

	private Handler mHandler = new Handler();

	private ListView lv_content;
	private String[] yearArray = {"鼠年", "牛年", "虎年", "兔年", "龍年", "蛇年",
			"馬年", "羊年", "猴年", "雞年", "狗年", "豬年"};
	private void refreshView() {
		TitleListAdapter adapter = new TitleListAdapter(this, yearArray);
		lv_content.setAdapter(adapter);
		lv_content.setOnItemClickListener(adapter);
		lv_content.setOnItemLongClickListener(adapter);
	}

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_listview);

		tv_listview = (TextView) findViewById(R.id.tv_listview);
		srl_listview = (SwipeRefreshLayout) findViewById(R.id.srl_listview);
		srl_listview.setOnRefreshListener(this);
		//舊版用下面的setColorScheme設置進度條顏色
		srl_listview.setColorScheme(R.color.red, R.color.orange, R.color.green, R.color.blue);
		//新版用下面的setColorSchemeResources設置進度圓圈顏色
//		srl_listview.setColorSchemeResources(
//				R.color.red, R.color.orange, R.color.green, R.color.blue );
		
		lv_content = (ListView) findViewById(R.id.lv_content);
		refreshView();
	}

	@Override
	public void onRefresh() {
		tv_listview.setVisibility(View.VISIBLE);
		tv_listview.setText("正在刷新");
		mHandler.postDelayed(mRefresh, 3000);
	}
	
	private Runnable mRefresh = new Runnable() {

		@Override
		public void run() {
			refreshView();
			tv_listview.setText("刷新完成");
			srl_listview.setRefreshing(false);
			mHandler.postDelayed(mComplete, 500);
		}
		
	};

	private Runnable mComplete = new Runnable() {

		@Override
		public void run() {
			tv_listview.setVisibility(View.GONE);
		}
		
	};

}


SwipeRefreshLayout+RecyclerView下拉刷新

看過了搭配ListView的下拉刷新,再來看看搭配RecyclerView會是什麼效果。上面我們看到搭配ListView的情況下,在刷新開始與刷新結束時,提示文字的展示與隱藏過程有點突兀,都是一下子展示和一下子隱藏,缺乏動畫效果,使人覺得生硬呆板。那麼搭配RecyclerView進行下拉刷新有沒有辦法改善這種情況呢?


下面是SwipeRefreshLayout+RecyclerView的下拉刷新效果截圖:
\


從上面截圖可以發現,提示文字的出現和消失都伴隨著動畫,整體效果顯得柔和許多,而這有賴於RecyclerView的局部更新特性。復習一下前篇博文《Android開發筆記(一百二十二)循環器視圖RecyclerView》,當時我們提到RecyclerView的幾個方法,卻沒有實際運用的例子,現在正好派上用場了。它們是:
1、RecyclerView.Adapter的notify相關方法,如notifyItemInserted、notifyItemRemoved、notifyItemChanged,用於在個別項目發生變化時單獨通知適配器調整。
2、GridLayoutManager的setSpanSizeLookup方法,對於第一個元素,可指定讓它占滿第一行作為頭部區域,從而把提示區域納入整個列表視圖的統一管理。
3、GridLayoutManager的setLayoutManager方法,在布局管理信息發生變化時,隨時調用該方法生效最新的布局配置,這樣列表項的增刪操作就能顯示動畫效果。


下面是SwipeRefreshLayout+RecyclerView的頁面代碼示例:
import java.util.LinkedList;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.example.exmswipe.adapter.RecyclerAdapter;

public class RecyclerActivity extends Activity implements OnRefreshListener {
	
	private SwipeRefreshLayout srl_recycler;

	private Handler mHandler = new Handler();

	private int mColumnCount = 3;
	private RecyclerView rv_content;
	private GridLayoutManager mLayoutManager;
	private RecyclerAdapter mAdapter;
	private String[] yearArray = {"鼠年", "牛年", "虎年", "兔年", "龍年", "蛇年",
			"馬年", "羊年", "猴年", "雞年", "狗年", "豬年"};
	private LinkedList<string> mYearList = new LinkedList<string>();
	private void refreshView() {
		mAdapter = new RecyclerAdapter(this, 2, mYearList);
		rv_content.setAdapter(mAdapter);
		mAdapter.setOnItemClickListener(mAdapter);
		mAdapter.setOnItemLongClickListener(mAdapter);
	}

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_recycler);

		srl_recycler = (SwipeRefreshLayout) findViewById(R.id.srl_recycler);
		srl_recycler.setOnRefreshListener(this);
		//舊版用下面的setColorScheme設置進度條顏色
		srl_recycler.setColorScheme(R.color.red, R.color.orange, R.color.green, R.color.blue);
		//新版用下面的setColorSchemeResources設置進度圓圈顏色
//		srl_recycler.setColorSchemeResources(
//				R.color.red, R.color.orange, R.color.green, R.color.blue );
		
		rv_content = (RecyclerView) findViewById(R.id.rv_content);
		mLayoutManager = new GridLayoutManager(this, mColumnCount);
		mLayoutManager.setSpanSizeLookup(new MySpanRule(-1));
		rv_content.setLayoutManager(mLayoutManager);
		for (int i=0; i<yeararray.length; override="" public="" void="" new="" private="" runnable="" mrefresh="new" mcomplete="new" class="" myspanrule="" extends="" gridlayoutmanager.spansizelookup="" int="" mposition="=" if="" return="" else="" position="=" pre="">

SwipeRefreshLayout實現上拉加載

SwipeRefreshLayout默認只實現下拉刷新功能,沒有上拉加載功能;如果我們要用它來做上拉加載,就得想辦法自定義控件了。從網上資料來看,大家給SwipeRefreshLayout添加上拉加載主要有兩種思路: 1、重寫SwipeRefreshLayout,在dispatchTouchEvent方法中捕獲上拉事件,並進行合理性校驗之後,觸發上拉加載操作。 2、調用RecyclerView的setOnTouchListener方法,並實現一個觸摸監聽器傳給該方法,監聽器中也是一樣捕獲上拉事件並進行後續處理。但是該方法不能與SwipeRefreshLayout直接共存,因為SwipeRefreshLayout與ScrollView一樣,都會自動攔截上下滑動的手勢,如此一來,上下滑動事件都被SwipeRefreshLayout先攔截了,哪裡還會傳給下面的RecyclerView呢?所以要麼只用RecyclerView不用SwipeRefreshLayout,要麼就是重寫SwipeRefreshLayout讓它放過上拉事件。 上面兩種思路都有對應的實現代碼,可是我覺得,SwipeRefreshLayout作為Android的原生控件,就應該讓它去做它擅長的事情。如果要它實現上拉加載還得大動干戈的話,不如直接使用下拉刷新的開源框架PullToRefresh,因為PullToRefresh能夠實現的功能更加強大,如果都要大費周章,為什麼我們不用更好的呢?所以我以為上拉加載功能最好還是用PullToRefresh
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved