




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用ListView實(shí)現(xiàn)下拉加載功能
Android中怎么利用ListView實(shí)現(xiàn)下拉加載功能,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。1、MyListView.Javapublic
class
MyListView
extends
ListView
implements
OnScrollListener
{
private
final
static
int
RELEASE_To_REFRESH
=
0;//
下拉過程的狀態(tài)值
private
final
static
int
PULL_To_REFRESH
=
1;
//
從下拉返回到不刷新的狀態(tài)值
private
final
static
int
REFRESHING
=
2;//
正在刷新的狀態(tài)值
private
final
static
int
DONE
=
3;
private
final
static
int
LOADING
=
4;
//
實(shí)際的padding的距離與界面上偏移距離的比例
private
final
static
int
RATIO
=
3;
private
LayoutInflater
inflater;
//
ListView頭部下拉刷新的布局
private
LinearLayout
headerView;
private
TextView
lvHeaderTipsTv;
private
TextView
lvHeaderLastUpdatedTv;
private
ImageView
lvHeaderArrowIv;
private
ProgressBar
lvHeaderProgressBar;
//
定義頭部下拉刷新的布局的高度
private
int
headerContentHeight;
private
RotateAnimation
animation;
private
RotateAnimation
reverseAnimation;
private
int
startY;
private
int
state;
private
boolean
isBack;
//
用于保證startY的值在一個(gè)完整的touch事件中只被記錄一次
private
boolean
isRecored;
private
OnRefreshListener
refreshListener;
private
boolean
isRefreshable;
public
MyListView(Context
context)
{
super(context);
init(context);
}
public
MyListView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
init(context);
}
private
void
init(Context
context)
{
inflater
=
LayoutInflater.from(context);
headerView
=
(LinearLayout)
inflater.inflate(R.layout.lv_header,
null);
lvHeaderTipsTv
=
(TextView)
headerView
.findViewById(R.id.lvHeaderTipsTv);
lvHeaderLastUpdatedTv
=
(TextView)
headerView
.findViewById(R.id.lvHeaderLastUpdatedTv);
lvHeaderArrowIv
=
(ImageView)
headerView
.findViewById(R.id.lvHeaderArrowIv);
//
設(shè)置下拉刷新圖標(biāo)的最小高度和寬度
lvHeaderArrowIv.setMinimumWidth(70);
lvHeaderArrowIv.setMinimumHeight(50);
lvHeaderProgressBar
=
(ProgressBar)
headerView
.findViewById(R.id.lvHeaderProgressBar);
measureView(headerView);
headerContentHeight
=
headerView.getMeasuredHeight();
//
設(shè)置內(nèi)邊距,正好距離頂部為一個(gè)負(fù)的整個(gè)布局的高度,正好把頭部隱藏
headerView.setPadding(0,
-1
*
headerContentHeight,
0,
0);
//
重繪一下
headerView.invalidate();
//
將下拉刷新的布局加入ListView的頂部
addHeaderView(headerView,
null,
false);
//
設(shè)置滾動(dòng)監(jiān)聽事件
setOnScrollListener(this);
//
設(shè)置旋轉(zhuǎn)動(dòng)畫事件
animation
=
new
RotateAnimation(0,
-180,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
animation.setInterpolator(new
LinearInterpolator());
animation.setDuration(250);
animation.setFillAfter(true);
reverseAnimation
=
new
RotateAnimation(-180,
0,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
reverseAnimation.setInterpolator(new
LinearInterpolator());
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);
//
一開始的狀態(tài)就是下拉刷新完的狀態(tài),所以為DONE
state
=
DONE;
//
是否正在刷新
isRefreshable
=
false;
}
@Override
public
void
onScrollStateChanged(AbsListView
view,
int
scrollState)
{
}
@Override
public
void
onScroll(AbsListView
view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount)
{
if
(firstVisibleItem
==
0)
{
isRefreshable
=
true;
}
else
{
isRefreshable
=
false;
}
}
@Override
public
boolean
onTouchEvent(MotionEvent
ev)
{
if
(isRefreshable)
{
switch
(ev.getAction())
{
case
MotionEvent.ACTION_DOWN:
if
(!isRecored)
{
isRecored
=
true;
startY
=
(int)
ev.getY();//
手指按下時(shí)記錄當(dāng)前位置
}
break;
case
MotionEvent.ACTION_UP:
if
(state
!=
REFRESHING
&&
state
!=
LOADING)
{
if
(state
==
PULL_To_REFRESH)
{
state
=
DONE;
changeHeaderViewByState();
}
if
(state
==
RELEASE_To_REFRESH)
{
state
=
REFRESHING;
changeHeaderViewByState();
onLvRefresh();
}
}
isRecored
=
false;
isBack
=
false;
break;
case
MotionEvent.ACTION_MOVE:
int
tempY
=
(int)
ev.getY();
if
(!isRecored)
{
isRecored
=
true;
startY
=
tempY;
}
if
(state
!=
REFRESHING
&&
isRecored
&&
state
!=
LOADING)
{
//
保證在設(shè)置padding的過程中,當(dāng)前的位置一直是在head,否則如果當(dāng)列表超出屏幕的話,當(dāng)在上推的時(shí)候,列表會(huì)同時(shí)進(jìn)行滾動(dòng)
//
可以松手去刷新了
if
(state
==
RELEASE_To_REFRESH)
{
setSelection(0);
//
往上推了,推到了屏幕足夠掩蓋head的程度,但是還沒有推到全部掩蓋的地步
if
(((tempY
-
startY)
/
RATIO
<
headerContentHeight)//
由松開刷新狀態(tài)轉(zhuǎn)變到下拉刷新狀態(tài)
&&
(tempY
-
startY)
>
0)
{
state
=
PULL_To_REFRESH;
changeHeaderViewByState();
}
//
一下子推到頂了
else
if
(tempY
-
startY
<=
0)
{//
由松開刷新狀態(tài)轉(zhuǎn)變到done狀態(tài)
state
=
DONE;
changeHeaderViewByState();
}
}
//
還沒有到達(dá)顯示松開刷新的時(shí)候,DONE或者是PULL_To_REFRESH狀態(tài)
if
(state
==
PULL_To_REFRESH)
{
setSelection(0);
//
下拉到可以進(jìn)入RELEASE_TO_REFRESH的狀態(tài)
if
((tempY
-
startY)
/
RATIO
>=
headerContentHeight)
{//
由done或者下拉刷新狀態(tài)轉(zhuǎn)變到松開刷新
state
=
RELEASE_To_REFRESH;
isBack
=
true;
changeHeaderViewByState();
}
//
上推到頂了
else
if
(tempY
-
startY
<=
0)
{//
由DOne或者下拉刷新狀態(tài)轉(zhuǎn)變到done狀態(tài)
state
=
DONE;
changeHeaderViewByState();
}
}
//
done狀態(tài)下
if
(state
==
DONE)
{
if
(tempY
-
startY
>
0)
{
state
=
PULL_To_REFRESH;
changeHeaderViewByState();
}
}
//
更新headView的size
if
(state
==
PULL_To_REFRESH)
{
headerView.setPadding(0,
-1
*
headerContentHeight
+
(tempY
-
startY)
/
RATIO,
0,
0);
}
//
更新headView的paddingTop
if
(state
==
RELEASE_To_REFRESH)
{
headerView.setPadding(0,
(tempY
-
startY)
/
RATIO
-
headerContentHeight,
0,
0);
}
}
break;
default:
break;
}
}
return
super.onTouchEvent(ev);
}
//
當(dāng)狀態(tài)改變時(shí)候,調(diào)用該方法,以更新界面
private
void
changeHeaderViewByState()
{
switch
(state)
{
case
RELEASE_To_REFRESH:
lvHeaderArrowIv.setVisibility(View.VISIBLE);
lvHeaderProgressBar.setVisibility(View.GONE);
lvHeaderTipsTv.setVisibility(View.VISIBLE);
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
lvHeaderArrowIv.clearAnimation();//
清除動(dòng)畫
lvHeaderArrowIv.startAnimation(animation);//
開始動(dòng)畫效果
lvHeaderTipsTv.setText("松開刷新");
break;
case
PULL_To_REFRESH:
lvHeaderProgressBar.setVisibility(View.GONE);
lvHeaderTipsTv.setVisibility(View.VISIBLE);
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.setVisibility(View.VISIBLE);
//
是由RELEASE_To_REFRESH狀態(tài)轉(zhuǎn)變來的
if
(isBack)
{
isBack
=
false;
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.startAnimation(reverseAnimation);
lvHeaderTipsTv.setText("下拉刷新");
}
else
{
lvHeaderTipsTv.setText("下拉刷新");
}
break;
case
REFRESHING:
headerView.setPadding(0,
0,
0,
0);
lvHeaderProgressBar.setVisibility(View.VISIBLE);
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.setVisibility(View.GONE);
lvHeaderTipsTv.setText("正在刷新...");
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
break;
case
DONE:
headerView.setPadding(0,
-1
*
headerContentHeight,
0,
0);
lvHeaderProgressBar.setVisibility(View.GONE);
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.setImageResource(R.drawable.arrow);
lvHeaderTipsTv.setText("下拉刷新");
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
break;
}
}
//
此方法直接照搬自網(wǎng)絡(luò)上的一個(gè)下拉刷新的demo,此處是“估計(jì)”headView的width以及height
private
void
measureView(View
child)
{
ViewGroup.LayoutParams
params
=
child.getLayoutParams();
if
(params
==
null)
{
params
=
new
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int
childWidthSpec
=
ViewGroup.getChildMeasureSpec(0,
0
+
0,
params.width);
int
lpHeight
=
params.height;
int
childHeightSpec;
if
(lpHeight
>
0)
{
childHeightSpec
=
MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
}
else
{
childHeightSpec
=
MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec,
childHeightSpec);
}
public
void
setonRefreshListener(OnRefreshListener
refreshListener)
{
this.refreshListener
=
refreshListener;
isRefreshable
=
true;
}
public
interface
OnRefreshListener
{
public
void
onRefresh();
}
public
void
onRefreshComplete()
{
state
=
DONE;
lvHeaderLastUpdatedTv.setText("最近更新:"
+
new
Date().toLocaleString());
changeHeaderViewByState();
}
private
void
onLvRefresh()
{
if
(refreshListener
!=
null)
{
refreshListener.onRefresh();
}
}
public
void
setAdapter(LvAdapter
adapter)
{
lvHeaderLastUpdatedTv.setText("最近更新:"
+
new
Date().toLocaleString());
super.setAdapter(adapter);
}
}2、MainActivity.javapublic
class
MainActivity
extends
Activity
{
private
List<String>
list;
private
MyListView
lv;
private
LvAdapter
adapter;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv
=
(MyListView)
findViewById(R.id.lv);
list
=
new
ArrayList<String>();
list.add("loonggg");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
list.add("我們都是開發(fā)者");
adapter
=
new
LvAdapter(list,
this);
lv.setAdapter(adapter);
lv.setonRefreshListener(new
OnRefreshListener()
{
@Override
public
void
onRefresh()
{
new
AsyncTask<Void,
Void,
Void>()
{
protected
Void
doInBackground(Void...
params)
{
try
{
Thread.sleep(1000);
}
catch
(Exception
e)
{
e.printStackTrace();
}
list.add("刷新后添加的內(nèi)容");
return
null;
}
@Override
protected
void
onPostExecute(Void
result)
{
adapter.notifyDataSetChanged();
lv.onRefreshComplete();
}
}.execute(null,
null,
null);
}
});
}
}3、LvAdapterpublicclassLvAdapterextendsBaseAdapter{
privateList<String>list;
privateContextcontext;
publicLvAdapter(List<String>list,Contextcontext){
this.list=list;
this.context=context;
}
@Override
publicintgetCount(){
returnlist.size();
}
@Override
publicObjectgetItem(intposition){
returnlist.get(position);
}
@Override
publiclonggetItemId(intposition){
returnposition;
}
@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
TextViewtv=newTextView(context.getApplicationContext());
tv.setText(list.get(position));
returntv;
}
}
4、lv_header.xml[html]viewplaincopy<LinearLayoutxmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#000000">
<!--內(nèi)容-->
<RelativeLayout
android:id="@+id/head_contentLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp">
<!--箭頭圖像、進(jìn)度條-->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true">
<!--箭頭-->
<ImageView
android:id="@+id/lvHeaderArrowIv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/arrow"/>
<!--進(jìn)度條-->
<ProgressBar
android:id="@+id/lvHeaderProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"/>
</FrameLayout>
<!--提示、最近更新-->
<LinearLayout
android:l
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 宿遷輔警考試題庫2025(有答案)
- 2025年山東省環(huán)保發(fā)展集團(tuán)有限公司招聘考試試題(含答案)
- 2025年白板市場(chǎng)調(diào)研報(bào)告
- 景觀園林彩鋼房安裝與維護(hù)合同
- 餐飲業(yè)員工權(quán)益保護(hù)與勞動(dòng)仲裁協(xié)議
- 科技園區(qū)場(chǎng)地及研發(fā)中心租賃合同模板
- 焊工安全操作規(guī)程及安全注意事項(xiàng)
- 保密自查自評(píng)報(bào)告2025
- 法規(guī)制度學(xué)習(xí)
- 2025至2030新媒體行業(yè)產(chǎn)業(yè)運(yùn)行態(tài)勢(shì)及投資規(guī)劃深度研究報(bào)告
- 中央廚房食品項(xiàng)目經(jīng)營分析報(bào)告
- 小學(xué)四年級(jí)道德與法治期末考試質(zhì)量分析
- 鉗工實(shí)操試卷-共44套
- 論融資租賃資產(chǎn)證券化在我國存在的必要性
- 麻醉藥品精神藥品管理培訓(xùn)課件
- QCC品管圈活動(dòng)表格匯編
- 2023年貴州省社區(qū)工作者公開招聘考試《公共基礎(chǔ)知識(shí)》專項(xiàng)題庫【真題精選+章節(jié)題庫+模擬試題】
- 出租車大包車合同
- 銀行副行長個(gè)人簡歷表格
- 第四講 堅(jiān)持以人民為中心PPT習(xí)概論2023優(yōu)化版教學(xué)課件
- 醫(yī)院全員聘用制度和崗位聘任管理制度
評(píng)論
0/150
提交評(píng)論