版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用ListView實(shí)現(xiàn)下拉加載功能
Android中怎么利用ListView實(shí)現(xiàn)下拉加載功能,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。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)變來(lái)的
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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 消防設(shè)施招投標(biāo)合同
- 大型場(chǎng)館建設(shè)合同樣式
- 食品加工三方施工合同
- 機(jī)場(chǎng)VIP室花卉租用協(xié)議
- 劇院清潔工招聘協(xié)議書
- 兒童玩具專賣店裝修施工合同
- 游艇碼頭建造師合同模板
- 豪華郵輪廚師長(zhǎng)聘用合同
- 地鐵站雨污治理工程協(xié)議
- 服裝店財(cái)務(wù)人員勞動(dòng)合同
- 物理實(shí)驗(yàn)知到智慧樹章節(jié)測(cè)試課后答案2024年秋沈陽(yáng)理工大學(xué)
- 高血壓課件教學(xué)課件
- 孕期常見癥狀及處理課件
- 《2025酒店預(yù)算的進(jìn)與退》
- 肺癌的介入治療護(hù)理
- 民辦學(xué)校教職工入職背景審查制度
- 軟件驗(yàn)收合同范本(2篇)
- 立式儲(chǔ)罐課課程設(shè)計(jì)
- 2024年區(qū)第三期機(jī)關(guān)、事業(yè)單位公開選調(diào)工作人員考試題及答案
- 珠寶玉石鑒定學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 管理學(xué)(A)(2022-2023-1學(xué)期)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
評(píng)論
0/150
提交評(píng)論