ListView實現上拉載入&下拉重新整理
上拉載入&下拉重新整理
思路詳解:
自定義的帶有下拉重新整理和上拉載入的ListView開始時,跟系統的ListView一樣。不過多了個header和footer只不過這兩個佈局以不同的方式隱藏起來了而已。(header是在手機螢幕外的上面,footer是直接隱藏起來了。因為下拉和上拉載入不同,下拉載入有手勢判斷,要出現動畫效果,根據下拉的各種手勢,來設定具體的操作。如果直接跟footer一樣首先預設header的View.setVisibility(GONE),當有下拉手勢時再設定View.setVisibility(View.VISIBLE)就會沒有良好的動畫效果。)
如下圖所示:
上拉載入:
上拉載入適用於需要載入的資料量很大時,如果一下子載入完。會使ListView出現卡頓。這時候,如果利用上拉載入。先載入一部分資料。當上拉時,再載入其他的一部分資料。這樣就會有很好的使用者體驗。
接下來看上拉載入邏輯:上拉載入我們利用的是AbsListView.OnScrollListener這個介面。 它有兩個方法需要重寫:
1.publicvoid onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) {}; //滾動時一直回撥,直到停止滾動時才停止回撥。單擊時回撥一次。 //firstVisibleItem:當前能看見的第一個列表項ID(從0開始) //visibleItemCount:當前能看見的列表項個數(小半個也算) //totalItemCount:列表項共數
2.publicvoid onScrollStateChanged(AbsListView view,int scrollState) {}; //正在滾動時回撥,回撥2-3次,手指沒拋則回撥2次。scrollState = 2的這次不回撥 //回撥順序如下 //第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滾動 //第2次:scrollState = SCROLL_STATE_FLING(2) 手指做了拋的動作(手指離開螢幕前,用力滑了一下) //第3次:scrollState = SCROLL_STATE_IDLE(0) 停止滾動 //當螢幕停止滾動時為0;當螢幕滾動且使用者使用的觸碰或手指還在螢幕上時為1; //由於使用者的操作,螢幕產生慣性滑動時為2 //當滾到最後一行且停止滾動時,執行載入
自定義LoadListView
1.定義變數
private int lastVisibleItem; //最後一個可見項
private int totalItems; //總的item
private View footer; //底部View+頭部View;
private boolean isLoading = false;//是否正在載入
private ILoadListener iListener;//自定義的一個載入介面。暴露給MainActivity讓它實現具體載入操作。可以根據需求不同而改寫。
2.載入佈局檔案及設定監聽
private void initViews(Context context) {
//獲得footer+header佈局檔案
LayoutInflater inflater =LayoutInflater.from(context);
footer = inflater.inflate(R.layout.footer,null);
footer.findViewById(R.id.ll_footer).setVisibility(GONE);//初始化時設定footer不可見
this.addFooterView(footer);
this.setOnScrollListener(this);//設定滾動監
}
3.重寫OnScrollListener的兩個方法
4.完成介面設定
/**
* 載入更多資料的回撥介面
*/
public interface ILoadListener {
public void onLoad();
}
//上拉載入完畢
public void loadCompleted(){
isLoading =false;
footer.findViewById(R.id.ll_footer).setVisibility(GONE);
}
public void setInterface(ILoadListener iListener){
this.iListener=iListener;
}
5.在MainActivity中實現LoadListView暴露的介面中的onLoad方法
//實現onLoad()方法。
@Override
public void onLoad() {
//新增延時效果模擬資料載入
Handler handler= new Handler() ;
handler.postDelayed(new Runnable() {
@Override
public void run() {
initNewDatas();//得到新資料
arrayAdapter.notifyDataSetChanged();//重新整理ListView;
mListView.loadCompleted();
}
}, 2000);
}
上拉載入資料完成。
下拉重新整理:
1.header佈局檔案
2.在LoadListView中定義變數
private boolean isRemark = false;//判斷是否在當前頁的最頂端並下滑
private int startY; //Y座標 記錄手指開始按下的座標
private RLoadListener rLoadListener;//自定義的一個載入介面。暴露給MainActivity讓它實現具體載入操作。可以根據需求不同而改寫。
private int scrollState;//當前滾動的 狀態
private int headerHeight;//頂部佈局檔案的高度
final int NONE= 0;//正常狀態
final int PULL =1;//下拉
final int RELESE =2;//釋放
final int REFLASHING =3; //重新整理
private int state=0;//判斷當前狀態,預設為正常狀態
private int firstVisibleItem;//第一個可見項
private View header; //頭部View;
3.新增頭部到ListView中
這裡新增頭佈局的時候需要計算header到底要移出螢幕多少的距離(移出的距離即為header的高),並且要告知父佈局
4.在OnScrollListener的兩個方法中記錄一些狀態量便於後面對OnTouch事件的操作
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.scrollState =scrollState;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int
totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
}
5.利用OnTouchEvent對下拉手勢操作進行監聽:
先來說明下拉重新整理會出現的情況:
1.下拉距離過短,不進行資料重新整理。
2.下拉到一定距離重新整理資料。
當進行下拉重新整理的時候,手勢有3種狀態:
1.剛按下的時候;
2.手指下滑移動的時候;
3.手指擡起釋放的時候。
這3種手指狀態又對應了header不同的View狀態,然後根據view的狀態,再來改變header的顯示。
6.下拉重新整理介面,暴露給MainActivity來具體實現到底刷新出什麼資料:
/**
* 下拉重新整理介面
*/
public interface RLoadListener{
public void onRefresh();
}
public void setReflashInterface(RLoadListener rLoadListener){
this.rLoadListener =rLoadListener;
}
7.重新整理完要做的工作
/**
* 獲取完整資料
*
*/
public void reflashComplete(){
state = NONE;
isRemark = false;
reflashViewByState();
TextView lasetupdate_time = (TextView) header.findViewById(R.id.tv_lastupdate_time);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
Date date = new Date(System.currentTimeMillis());
String time = simpleDateFormat.format(date);
lasetupdate_time.setText(time);
}
8.在MainActivity中應用LoadListView
SwipeRefreshLayout實現下拉重新整理(僅效果)
- isRefreshing()
判斷當前的狀態是否是重新整理狀態。
- setColorSchemeResources(int... colorResIds)
設定下拉進度條的顏色主題,引數為可變引數,並且是資源id,可以設定多種不同的顏色,每轉一圈就顯示一種顏色。
- setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)
設定監聽,需要重寫onRefresh()方法,頂部下拉時會呼叫這個方法,在裡面實現請求資料的邏輯,設定下拉進度條消失等等。
- setProgressBackgroundColorSchemeResource(int colorRes)
設定下拉進度條的背景顏色,預設白色。
- setRefreshing(boolean refreshing)
設定重新整理狀態,true表示正在重新整理,false表示取消重新整理。
使用:
1.設定佈局
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>
2.在程式碼中使用
在該佈局檔案對應的Activity或其他類中獲取佈局id,先設定ListView顯示的介面卡,然後再設定SwipeRefreshLayout。
注:不能在onCreate中設定,這個表示當前是重新整理狀態,如果一進來就是重新整理狀態,SwipeRefreshLayout會遮蔽掉下拉事件 //swipeRefreshLayout.setRefreshing(true);
//宣告控制元件
private SwipeRefreshLayout swiper;
private ListView mListView;
//宣告並初始化ListView的資料來源
private List<String> list = new ArrayList<>();
//宣告ListView的介面卡
private ArrayAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.swipe_layout);
//初始化SwipeRefreshLayout
swiper = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
//為SwipeRefreshLayout設定監聽事件
swiper.setOnRefreshListener(this);
//為SwipeRefreshLayout設定重新整理時的顏色變化,最多可以設定4種
swiper.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
//初始化ListView
mListView = (ListView) findViewById(R.id.list_view);
//初始化介面卡
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData());
//設定介面卡
mListView.setAdapter(adapter);
}
//增加資料
private List<String> getData() {
list.add("hello");
list.add("this is johnsonHou");
list.add("an android rookie developer");
list.add("love android");
return list;
}
//實現OnRefreshListener 的onRefresh()方法
@Override
public void onRefresh() {
//重新整理
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//結束後停止重新整理
swiper.setRefreshing(false);
}
}, 3000);
}
//簡單示例,手動新增資料
private void refreshData() {
list.add(0, String.valueOf((int) (Math.random() * 10)));
adapter.notifyDataSetChanged();
}