Android自定義控件ListView下拉刷新的代碼
ListView在實(shí)際實(shí)用中,一般都會有下新刷新和上拉加載的動態(tài)效果,今天要學(xué)的就是如何自定義帶下拉刷新的ListView。
原理解析:一般將有下拉刷新的listview分成四種不同的狀態(tài)來進(jìn)行不同的顯示效果。
- 1.完成狀態(tài)done:listview正常顯示狀態(tài)
- 2.下拉狀態(tài)pull:listview正在下拉時的狀態(tài)
- 3.釋放狀態(tài)release:listview下拉后松開的狀態(tài)
- 4.更新狀態(tài)refreshing:listview下拉后加載數(shù)據(jù)時的狀態(tài)
實(shí)現(xiàn)步驟:
- 自定義CustomListView繼承自ListView,添加headerView,里面的布局是有下拉刷新的文字與圖片
- 為listview創(chuàng)建適配器,隨便弄一些數(shù)據(jù)做一些數(shù)據(jù)源放入到listview的適配器中,好測試顯示。
- 自定義的帶有頭部的ListView首先要將頭部視圖隱藏掉,添加頭視圖的代碼是listview.addHeaderView()。
- 注意:這里并不能用headerView對象的setVisibility()來實(shí)現(xiàn)隱藏的效果,當(dāng)你調(diào)用這個添加頭部視圖的方法時,頭部位置不管有沒有視圖都會占據(jù)一個位置。所以得用setPadding()的TOP為負(fù)數(shù)來實(shí)現(xiàn)這個功能。
- 具體代碼實(shí)現(xiàn)
package com.hapzhu.customlv;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
public class CustomListview extends ListView {
View headerView;
int height;
private TextView tvActionTip;
private ImageView ivArrow;
private ProgressBar pbRefreshing;
final static int STATE_DONE = 1;
final static int STATE_PULL = 2;
final static int STATE_RELEASE = 3;
final static int STATE_REFRESHING = 4;
int currentState;
int downY;
public CustomListview(Context context, AttributeSet attrs) {
super(context, attrs);
headerView = View.inflate(context, R.layout.listview_header, null);
this.addHeaderView(headerView);
// 用setPadding方法設(shè)置Top的大小來把headerview隱藏掉
// 不能用GetHeight方法來實(shí)現(xiàn),因?yàn)檫@個方法只能用來測試可見的控件
// 要用measureHeight的方法來實(shí)現(xiàn)測試,這個方法要先測試0,0的位置
headerView.measure(0, 0);
height = headerView.getMeasuredHeight();
headerView.setPadding(0, -height, 0, 0);
initView();
// 設(shè)置第一個狀態(tài)
currentState = STATE_DONE;
}
private void initView() {
tvActionTip = (TextView) headerView.findViewById(R.id.tv_state);
ivArrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
pbRefreshing = (ProgressBar) headerView.findViewById(R.id.progressBar);
}
boolean isRefresh = false;
@Override
public boolean onTouchEvent(MotionEvent ev) {
try {
// 事件類型
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:// 往下滑的手勢
if (currentState == STATE_DONE) {// 只有在完成狀態(tài)時才會有業(yè)務(wù)動作
// 觸發(fā)下拉手勢的Y坐標(biāo)
downY = (int) ev.getY();
// 切換狀態(tài)
currentState = STATE_PULL;
}
break;
case MotionEvent.ACTION_MOVE:// 正在拖動的手勢
if (currentState == STATE_PULL) {// 只有在下拉狀態(tài)時才會有動作
int currentY = (int) ev.getY();// 得到正在不斷改變的當(dāng)前Y坐標(biāo)
int top = currentY - downY - height;// 這個值是下拉時頭部視圖的高度顯示,要慢慢變化
headerView.setPadding(0, top, 0, 0);
if (currentY - downY > height) {// 如果下拉的高度超過了頭視圖的高度,則改變狀態(tài)
currentState = STATE_RELEASE;
tvActionTip.setText("松開刷新");
}
}
break;
case MotionEvent.ACTION_UP:
if (currentState == STATE_RELEASE) {// 只有在釋放狀態(tài)時才進(jìn)行刷新動作
tvActionTip.setText("刷新中");// 改變文字 提示
currentState = STATE_REFRESHING;// 改變狀態(tài),變?yōu)樗⑿聽顟B(tài)
ivArrow.setVisibility(GONE);// 箭頭隱藏
pbRefreshing.setVisibility(VISIBLE);// 進(jìn)度條顯示
isRefresh = true;
if(onRefreshListener!=null){
//如果回調(diào)接口不為空,則進(jìn)行更新的事務(wù)
onRefreshListener.OnRefresh(this);
}
} else {
if (!isRefresh) {
// 如果當(dāng)前的下拉距離小于高度時,再把頭部視圖隱藏
headerView.setPadding(0, -height, 0, 0);
// 一定要記得把狀態(tài)改回去,不然會沒法再次向下拉
currentState = STATE_DONE;
}
}
break;
}
} catch (Exception e) {
}
return super.onTouchEvent(ev);
}
// 1定義接口
interface OnRefreshListener {
// 在主程序中使用框架中的Custom來改變數(shù)據(jù)更新完之后的界面
public void OnRefresh(CustomListview customLv);
}
// 2.申明接口
OnRefreshListener onRefreshListener;
// 3.傳遞接口
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}
public void refreshComplete(){
isRefresh=false;
//更新數(shù)據(jù)結(jié)果后,再回調(diào)這個方法
headerView.setPadding(0, -height, 0, 0);
// 一定要記得把狀態(tài)改回去,不然會沒法再次向下拉
currentState = STATE_DONE;
//將進(jìn)度條設(shè)為不可見,將箭頭設(shè)為可見,將文字改回去
ivArrow.setVisibility(VISIBLE);// 箭頭顯示
pbRefreshing.setVisibility(GONE);// 進(jìn)度條隱去
tvActionTip.setText("下拉刷新");// 改變文字 提示
}
}
今天新學(xué)了UML圖,于是就將這個狀態(tài)圖畫出來了。

總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
- Android自定義ListView實(shí)現(xiàn)下拉刷新上拉加載更多
- android RecycleView實(shí)現(xiàn)下拉刷新和上拉加載
- 解決android viewmodel 數(shù)據(jù)刷新異常的問題
- Android巧用XListView實(shí)現(xiàn)萬能下拉刷新控件
- Android自定義view仿微信刷新旋轉(zhuǎn)小風(fēng)車
- Android ExpandableListView實(shí)現(xiàn)下拉刷新和加載更多效果
- Android RecyclerView的刷新分頁的實(shí)現(xiàn)
- android使用SwipeRefreshLayout實(shí)現(xiàn)ListView下拉刷新上拉加載
- android使用PullToRefresh框架實(shí)現(xiàn)ListView下拉刷新上拉加載更多
- Android 中RecyclerView頂部刷新實(shí)現(xiàn)詳解
- Android四種方式刷新View的操作方法
相關(guān)文章
Kotlin 高階函數(shù)與Lambda表達(dá)式示例詳解
這篇文章主要為大家介紹了Kotlin 高階函數(shù)與Lambda表達(dá)式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android入門之IntentService的使用教程詳解
IntentService的生命周期中有一個非常好的方法-onHandleIntent方法,它是一個abstract方法,開發(fā)者在實(shí)現(xiàn)IntentService時可以覆蓋它來處理“長事務(wù)”。本文就來聊聊IntentService的使用,需要的可以參考一下2022-12-12
詳解Android studio ndk配置cmake開發(fā)native C
這篇文章主要介紹了詳解Android studio ndk配置cmake開發(fā)native C,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-09-09
Android編程入門之HelloWorld項(xiàng)目目錄結(jié)構(gòu)分析
這篇文章主要介紹了Android編程入門之HelloWorld項(xiàng)目目錄結(jié)構(gòu)分析,較為詳細(xì)的分析了Android項(xiàng)目的目錄結(jié)構(gòu)與具體作用,需要的朋友可以參考下2015-12-12
詳談OnTouchListener與OnGestureListener的區(qū)別
下面小編就為大家?guī)硪黄斦凮nTouchListener與OnGestureListener的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Android ContentProvider查看/讀取手機(jī)聯(lián)系人實(shí)例
本篇文章主要介紹了Android ContentProvider查看/讀取手機(jī)聯(lián)系人實(shí)例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02
Android 中 Swipe、Scroll 和 Fling 的區(qū)別解
Swipe、Scroll和Fling是Android中常見的觸摸手勢,它們在用戶體驗(yàn)和技術(shù)實(shí)現(xiàn)上各有特點(diǎn),Swipe用于快速切換,Scroll用于連續(xù)滾動,Fling用于實(shí)現(xiàn)慣性滾動,開發(fā)者可以根據(jù)需求選擇合適的手勢類型,并結(jié)合GestureDetector等工具實(shí)現(xiàn)各種交互效果,感興趣的朋友跟隨小編一起看看吧2024-12-12

