android listview下拉刷新动画,ListView下拉刷新实现方式详解和改造(上)
我們知道頁面的下拉刷新目前基本已經(jīng)成為智能移動終端的標配刷新方式。Twitter設(shè)計出現(xiàn)有的下拉刷新(在2013年申請了專利)。
下拉刷新1.jpg
這一優(yōu)美而又簡單的刷新方式,很快使得各大系統(tǒng)紛紛效仿;IOS在6.0開始引入,Android由于一開始不太重視交互體驗這方面,直到Android5.0開始才借鑒這樣一種刷新方式。那么我們今天就來研究研究怎么實現(xiàn)。
目前我收集到的不同方式有以下幾種:
方案一: listview headview調(diào)用setPadding的方式
方案二: listview的多種樣式顯示 getview 實現(xiàn)
方案三: SwipeRefreshLayout實現(xiàn)下來刷新 沒有加載更多
方案四:使用PullToRefresh 實現(xiàn)上拉加載和下拉刷新
方案五:使用Ultra-Pull-To-Refresh實現(xiàn)上拉加載和下拉刷新 類似方案三沒有加載更多
我們首先講解第一種實現(xiàn)方式,也是我們項目當(dāng)中經(jīng)常用到的。
實現(xiàn)思路:
1、首先為ListView添加頭布局和底布局,addHeadView()
2、通過改變HeaderView的paddingTop值,來控制控件的顯示和隱藏
3、根據(jù)我們滑動的狀態(tài),動態(tài)修改頭部布局。
listview.png
完整的刷新過程:
1、下拉刷新——2、釋放刷新——3、刷新中——1、下拉刷新
也就是分3種狀態(tài),那么分別什么時候切換狀態(tài)呢。看以下具體分析:
listview狀態(tài)圖.png
1、下拉刷新——釋放刷新:
當(dāng)headView的paddingTop的值從-headViewHeight減小到0時,說明此刻為釋放刷新;
2、釋放刷新——刷新中:
headView的paddingTop一直大于0時,此時松開手指,將headView固定在paddingTop為0的位置,此時也是剛好請求網(wǎng)絡(luò)的時機。
3、刷新中——下拉刷新:
刷新結(jié)束,paddingTop值由0重新回到-headViewHeight
代碼實現(xiàn)邏輯:
1、實現(xiàn) OnScrollListener 接口,在 onScroll() 方法中記錄當(dāng)前是否到頂部或者底部;
2、重寫 onTouchEvent() 方法,通過moveY - downY得到偏移量,將偏移量設(shè)置為HeadView的paddingTop,使HeadView跟隨手指移動產(chǎn)生變化;
3、onScrollStateChanged() 方法中根據(jù)狀態(tài)變化(開始滾動或停止?jié)L動),判斷是否需要加載更多。
4、定義了回調(diào)接口,讓用戶自己編寫下拉刷新的業(yè)務(wù)代碼;
完整代碼:
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
|| scrollState == OnScrollListener.SCROLL_STATE_FLING) {
if (isScroll2Bottom && !isLoadMoving) { // 滾動到底部
// 加載更多
if (!canLoadMore) {
return;
}
footerView.setPadding(0, 0, 0, 0);
this.setSelection(this.getCount()); // 滾動到ListView的底部
isLoadMoving = true;
//回調(diào)接口執(zhí)行請求加載
if (mOnRefreshListener != null) {
mOnRefreshListener.onLoadingMore();
}
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mFirstVisibleItem = firstVisibleItem;
isScroll2Bottom = (firstVisibleItem + visibleItemCount) >= totalItemCount
&& totalItemCount > 0;
}
public boolean onTouchEvent(MotionEvent ev) {
if (isEnd) {//如果現(xiàn)在時結(jié)束的狀態(tài),即刷新完畢了,可以再次刷新了,在onRefreshComplete中設(shè)置
if (isRefreable) {//如果現(xiàn)在是可刷新狀態(tài) 在setOnMeiTuanListener中設(shè)置為true
switch (ev.getAction()) {
//用戶按下
case MotionEvent.ACTION_DOWN:
//如果當(dāng)前是在listview頂部并且沒有記錄y坐標
if (mFirstVisibleItem == 0 && !isRecord) {
//將isRecord置為true,說明現(xiàn)在已記錄y坐標
isRecord = true;
//將當(dāng)前y坐標賦值給startY起始y坐標
startY = ev.getY();
}
break;
//用戶滑動
case MotionEvent.ACTION_MOVE:
//再次得到y(tǒng)坐標,用來和startY相減來計算offsetY位移值
float tempY = ev.getY();
//再起判斷一下是否為listview頂部并且沒有記錄y坐標
if (mFirstVisibleItem == 0 && !isRecord) {
isRecord = true;
startY = tempY;
}
//如果當(dāng)前狀態(tài)不是正在刷新的狀態(tài),并且已經(jīng)記錄了y坐標
if (state != REFRESHING && isRecord) {
//計算y的偏移量
offsetY = tempY - startY;
//如果當(dāng)前的狀態(tài)是放開刷新,并且已經(jīng)記錄y坐標
if (state == RELEASE_TO_REFRESH && isRecord) {
setSelection(0);
//如果當(dāng)前滑動的距離小于headerView的總高度
if (-mHeaderViewHeight + offsetY / RATIO < 0) {
//將狀態(tài)置為下拉刷新狀態(tài)
state = PULL_TO_REFRESH;
//根據(jù)狀態(tài)改變headerView,主要是更新動畫和文字等信息
changeHeaderByState(state);
//如果當(dāng)前y的位移值小于0,即為headerView隱藏了
} else if (offsetY <= 0) {
//將狀態(tài)變?yōu)閐one
state = DONE;
//根據(jù)狀態(tài)改變headerView,主要是更新動畫和文字等信息
changeHeaderByState(state);
}
}
//如果當(dāng)前狀態(tài)為下拉刷新并且已經(jīng)記錄y坐標
if (state == PULL_TO_REFRESH && isRecord) {
setSelection(0);
//如果下拉距離大于等于headerView的總高度
if (-mHeaderViewHeight + offsetY / RATIO >= 0) {
//將狀態(tài)變?yōu)榉砰_刷新
state = RELEASE_TO_REFRESH;
//根據(jù)狀態(tài)改變headerView,主要是更新動畫和文字等信息
changeHeaderByState(state);
//如果當(dāng)前y的位移值小于0,即為headerView隱藏了
} else if (offsetY <= 0) {
//將狀態(tài)變?yōu)閐one
state = DONE;
//根據(jù)狀態(tài)改變headerView,主要是更新動畫和文字等信息
changeHeaderByState(state);
}
}
//如果當(dāng)前狀態(tài)為done并且已經(jīng)記錄y坐標
if (state == DONE && isRecord) {
//如果位移值大于0
if (offsetY >= 0) {
//將狀態(tài)改為下拉刷新狀態(tài)
state = PULL_TO_REFRESH;
}
}
//如果為下拉刷新狀態(tài)
if (state == PULL_TO_REFRESH) {
//則改變headerView的padding來實現(xiàn)下拉的效果
headerView.setPadding(0, (int) (-mHeaderViewHeight + offsetY / RATIO), 0, 0);
}
//如果為放開刷新狀態(tài)
if (state == RELEASE_TO_REFRESH) {
//改變headerView的padding值
headerView.setPadding(0, (int) (-mHeaderViewHeight + offsetY / RATIO), 0, 0);
}
}
break;
//當(dāng)用戶手指抬起時
case MotionEvent.ACTION_UP:
//如果當(dāng)前狀態(tài)為下拉刷新狀態(tài)
if (state == PULL_TO_REFRESH) {
//平滑的隱藏headerView
headerView.setPadding(0, -mHeaderViewHeight, 0, 0);
//根據(jù)狀態(tài)改變headerView
changeHeaderByState(state);
}
//如果當(dāng)前狀態(tài)為放開刷新
if (state == RELEASE_TO_REFRESH) {
//平滑的滑到正好顯示headerView
headerView.setPadding(0, -mHeaderViewHeight, 0, 0);
//將當(dāng)前狀態(tài)設(shè)置為正在刷新
state = REFRESHING;
//回調(diào)接口的onRefresh方法
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
//根據(jù)狀態(tài)改變headerView
changeHeaderByState(state);
}
//這一套手勢執(zhí)行完,一定別忘了將記錄y坐標的isRecord改為false,以便于下一次手勢的執(zhí)行
isRecord = false;
break;
}
}
}
return super.onTouchEvent(ev);
}
那么到此,我們就把下拉刷新分析完了。
總結(jié)
以上是生活随笔為你收集整理的android listview下拉刷新动画,ListView下拉刷新实现方式详解和改造(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP/IP之IP协议(网际协议)
- 下一篇: Android钢琴滑动代码,androi