版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】自定義listview,支持上拉下拉刷新,自帶demo.
這個博客好想不能提供下載代碼啊,我只能把代碼貼出來了...其實你只需看用法,不用關(guān)心具體實現(xiàn),demo非常容易看懂public
class
CustomListViewActivity
extends
Activity
{
private
CustomListView
listview;
private
ArrayList<String>
data;
private
BaseAdapter
adapter;
/**
Called
when
the
activity
is
first
created.
*/
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
setListener();
}
private
void
init(){
data
=
new
ArrayList<String>();
//虛擬一些數(shù)據(jù)
data.add("a");
data.add("b");
data.add("c");
data.add("e");
data.add("f");
data.add("g");
data.add("h");
data.add("i");
data.add("j");
data.add("k");
data.add("L");
data.add("M");
data.add("L");
data.add("N");
data.add("O");
data.add("P");
data.add("Q");
listview
=
(CustomListView)
findViewById(R.id.listview);
adapter
=
new
BaseAdapter(){
@Override
public
int
getCount()
{
return
data.size();
}
@Override
public
Object
getItem(int
position)
{
return
null;
}
@Override
public
long
getItemId(int
position)
{
return
position;
}
@Override
public
View
getView(int
position,
View
convertView,
ViewGroup
parent)
{
TextView
textView
=
new
TextView(getApplicationContext());
textView.setHeight(100);
textView.setTextSize(20);
textView.setGravity(Gravity.CENTER);
textView.setBackgroundColor(0x66666666);
textView.setTextColor(0xaaffffff);
textView.setText(data.get(position));
return
textView;
}
};
listview.setAdapter(adapter);
}
private
void
setListener(){
listview.setOnRefreshListner(new
OnRefreshListner()
{
@Override
public
void
onRefresh()
{
new
AsyncTask<Void,
Void,
ArrayList<String>>(){
@Override
protected
ArrayList<String>
doInBackground(Void...
params)
{
try
{
//模擬從服務(wù)器獲取數(shù)據(jù)的過程
Thread.sleep(1500);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
ArrayList<String>
virtualData
=
new
ArrayList<String>();
virtualData.add("Head刷新后的新數(shù)據(jù)1");
virtualData.add("Head刷新后的新數(shù)據(jù)2");
virtualData.add("Head刷新后的新數(shù)據(jù)3");
virtualData.add("Head刷新后的新數(shù)據(jù)4");
virtualData.add("Head刷新后的新數(shù)據(jù)5");
virtualData.add("Head刷新后的新數(shù)據(jù)6");
return
virtualData;
}
//更新UI的方法,系統(tǒng)自動實現(xiàn)
@Override
protected
void
onPostExecute(ArrayList<String>
result)
{
data.addAll(0,result);//注意是往前添加數(shù)據(jù)
adapter.notifyDataSetChanged();
listview.onRefreshComplete();//完成下拉刷新,這個方法要調(diào)用
super.onPostExecute(result);
}
}.execute();
}
});
//創(chuàng)建FootView
final
View
footer
=
View.inflate(CustomListViewActivity.this,
R.layout.footer,
null);
listview.setOnAddFootListener(new
OnAddFootListener()
{
@Override
public
void
addFoot()
{
listview.addFooterView(footer);
}
});
listview.setOnFootLoadingListener(new
OnFootLoadingListener()
{
@Override
public
void
onFootLoading()
{
new
AsyncTask<Void,
Void,
ArrayList<String>>(){
@Override
protected
ArrayList<String>
doInBackground(Void...
params)
{
try
{
//模擬從服務(wù)器獲取數(shù)據(jù)的過程
Thread.sleep(2000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
ArrayList<String>
virtualData
=
new
ArrayList<String>();
virtualData.add("Foot刷新后的新數(shù)據(jù)1");
virtualData.add("Foot刷新后的新數(shù)據(jù)2");
virtualData.add("Foot刷新后的新數(shù)據(jù)3");
virtualData.add("Foot刷新后的新數(shù)據(jù)4");
virtualData.add("Foot刷新后的新數(shù)據(jù)5");
virtualData.add("Foot刷新后的新數(shù)據(jù)6");
return
virtualData;
}
//在doInBackground后面執(zhí)行
@Override
protected
void
onPostExecute(ArrayList<String>
result)
{
data.addAll(result);//這個是往后添加數(shù)據(jù)
adapter.notifyDataSetChanged();
listview.onFootLoadingComplete();//完成上拉刷新,就是底部加載完畢,這個方法要調(diào)用
//移除footer,這個動作不能少
listview.removeFooterView(footer);
super.onPostExecute(result);
}
}.execute();
}
});
}
}下面上listview的代碼,有點長.../**
*
支持下拉刷新和上拉刷新
*
可自定義上啦和下拉過程的操作,推薦使用AsyncTask
*
需自定義Foot的View,然后只需在addFoot方法中添加即可
*
@author
lxj
*
*/
public
class
CustomListView
extends
ListView
implements
OnScrollListener
{
private
static
final
int
DONE
=
0;
private
static
final
int
PULL_TO_REFRESH
=
1;
private
static
final
int
RELEASE_TO_REFRESH
=
2;
private
static
final
int
REFRESHING
=
3;
private
static
final
float
RATIO
=
3;//
用來設(shè)置實際間距和上邊距之間的比例
private
int
state;//
當(dāng)前下拉刷新的狀態(tài)
private
int
firstVisibleIndex;//
在listview中第一個可以看見的item
private
View
headView;
private
ImageView
headArrow;
private
ProgressBar
progressBar;
private
TextView
headTitle;
private
TextView
headLastUpdate;
private
int
headContentWidth;
private
int
headContentHeight;
private
Animation
animation;
private
Animation
reverseAnimation;
private
OnRefreshListner
refreshListner;//
刷新監(jiān)聽器
private
boolean
isRefreshable;
private
boolean
isRecored
=
false;//
用來記錄第一次按下坐標(biāo)點,在整個滑動的過程中
只記錄一次
private
float
startY;
private
boolean
isBack
=
false;//
是從
松開刷新狀態(tài)
來到的
下拉刷新狀態(tài)
public
CustomListView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
init(context);
}
private
void
init(Context
context)
{
//
listview
設(shè)置滑動時緩沖背景色
setCacheColorHint(0x00000000);
headView
=
View.inflate(context,
R.layout.head,
null);
headArrow
=
(ImageView)
headView.findViewById(R.id.head_arrow);
progressBar
=
(ProgressBar)
headView.findViewById(R.gressbar);
headTitle
=
(TextView)
headView.findViewById(R.id.head_title);
headLastUpdate
=
(TextView)
headView
.findViewById(R.id.head_last_update);
headArrow.setMinimumWidth(50);
headArrow.setMinimumHeight(70);
MeasureView(headView);
headContentWidth
=
headView.getMeasuredWidth();
headContentHeight
=
headView.getMeasuredHeight();
headView.setPadding(0,
-1*headContentHeight,
0,
0);
//
為listView加入頂部View
addHeaderView(headView);
setOnScrollListener(this);
animation
=
new
RotateAnimation(-180,
0,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
animation.setDuration(250);
animation.setFillAfter(true);//
設(shè)定動畫結(jié)束時,停留在動畫結(jié)束位置
(保留動畫效果)
animation.setInterpolator(new
LinearInterpolator());//
勻速變化
reverseAnimation
=
new
RotateAnimation(0,
-180,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);//
設(shè)定動畫結(jié)束時,停留在動畫結(jié)束位置
(保留動畫效果)
reverseAnimation.setInterpolator(new
LinearInterpolator());//
勻速變化
//
設(shè)置當(dāng)前headView的狀態(tài)
state
=
DONE;
//
設(shè)置當(dāng)前下拉刷新是否可用
isRefreshable
=
false;
}
/**
*
測量headView的
寬高
*
*
@param
child
*/
private
void
MeasureView(View
child)
{
ViewGroup.LayoutParams
lp
=
child.getLayoutParams();
if
(null
==
lp)
{
lp
=
new
ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
}
int
measureChildWidth
=
ViewGroup.getChildMeasureSpec(0,
0,
lp.width);
int
measureChildHeight;
if
(lp.height
>
0)
{
measureChildHeight
=
MeasureSpec.makeMeasureSpec(lp.height,
MeasureSpec.EXACTLY);
}
else
{
measureChildHeight
=
MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(measureChildWidth,
measureChildHeight);
}
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
switch
(event.getAction())
{
case
MotionEvent.ACTION_DOWN:
if
(firstVisibleIndex
==
0
&&
!isRecored)
{
startY
=
event.getY();
isRecored
=
true;
}
break;
case
MotionEvent.ACTION_MOVE:
float
tempY
=
event.getY();
if
(firstVisibleIndex
==
0
&&
!isRecored)
{
startY
=
tempY;
isRecored
=
true;
}
if
(state
!=
REFRESHING)
{
if
(state
==
PULL_TO_REFRESH)
{
//
向下拉了
從下拉刷新的狀態(tài)
來到
松開刷新的狀態(tài)
if
((tempY
-
startY)
/
RATIO
>=
headContentHeight
&&
(tempY
-
startY)
>
0)
{
state
=
RELEASE_TO_REFRESH;
changeHeadViewOfState();
}
//
向上推了
從下拉刷新的狀態(tài)
來到
刷新完成的狀態(tài)
else
if
((tempY
-
startY)
<=
0)
{
state
=
DONE;
changeHeadViewOfState();
}
}
else
if
(state
==
RELEASE_TO_REFRESH)
{
//
向上推了
還沒有完全將HEADVIEW
隱藏掉(可以看到一部分)
//
從松開刷新的狀態(tài)
來到
下拉刷新的狀態(tài)
if
((tempY
-
startY)
/
RATIO
<
headContentHeight
&&
(tempY
-
startY)
>
0)
{
state
=
PULL_TO_REFRESH;
changeHeadViewOfState();
isBack
=
true;
}
//
向上推了
一下子推到了最上面
從松開刷新的狀態(tài)
來到
刷新完成的狀態(tài)
(數(shù)據(jù)不刷新的)
else
if
((tempY
-
startY)
<=
0)
{
state
=
DONE;
changeHeadViewOfState();
}
}
else
if
(state
==
DONE)
{
//
刷新完成的狀態(tài)
來到
下拉刷新的狀態(tài)
if
((tempY
-
startY)
>
0)
{
state
=
PULL_TO_REFRESH;
changeHeadViewOfState();
}
}
if
(state
==
PULL_TO_REFRESH)
{
headView.setPadding(
0,
(int)
((tempY
-
startY)
/
RATIO
-
headContentHeight),
0,
0);
}
if
(state
==
RELEASE_TO_REFRESH)
{
headView.setPadding(
0,
(int)
((tempY
-
startY)
/
RATIO
-
headContentHeight),
0,
0);
}
}
break;
case
MotionEvent.ACTION_UP:
if
(state
!=
REFRESHING)
{
if
(state
==
PULL_TO_REFRESH)
{
//
松手
state
=
DONE;
changeHeadViewOfState();
}
else
if
(state
==
RELEASE_TO_REFRESH)
{
//
松手
state
=
REFRESHING;
changeHeadViewOfState();
//
執(zhí)行數(shù)據(jù)刷新方法
onRefresh();
}
}
isRecored
=
false;
isBack
=
false;
break;
}
return
super.onTouchEvent(event);
}
/**
*
執(zhí)行下拉刷新
*/
private
void
onRefresh()
{
if
(refreshListner
!=
null)
{
refreshListner.onRefresh();
}
}
/**
*
HeadView的狀態(tài)變化效果
*/
private
void
changeHeadViewOfState()
{
//
switch
(state)
{
case
PULL_TO_REFRESH:
headArrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headTitle.setText("下拉可以刷新");
//由
松開刷新
到
下拉刷新
if(isBack){
headArrow.startAnimation(animation);
isBack
=
false;
}
break;
case
RELEASE_TO_REFRESH:
headArrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headArrow.startAnimation(reverseAnimation);
headTitle.setText("松開可以刷新");
break;
case
REFRESHING:
headArrow.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headTitle.setText("正在刷新...");
headView.setPadding(0,
0,
0,
0);
break;
case
DONE:
headArrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headTitle.setText("下拉可以刷新");
headView.setPadding(0,
-1
*
headContentHeight,
0,
0);
break;
}
}
private
int
lastPos;//最后一個可見的item的位置
private
int
count;//item總數(shù),注意不是當(dāng)前可見的item總數(shù)
private
boolean
hasFoot
=
false;//是否有了Foot
@Override
public
void
onScroll(AbsListView
view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount)
{
firstVisibleIndex
=
firstVisibleItem;
lastPos
=
getLastVisiblePosition();
count
=
totalItemCount;
//因為剛進(jìn)入的時候,lastPos=-1,count=0,這個時候不能讓它執(zhí)行onAddFoot方法
if(lastPos==count-1
&&
!hasFoot
&&
lastPos
!=
-1){
hasFoot
=
true;
onAddFoot();
Log.d("addFoot================","執(zhí)行添加Foot");
}
Log.d("count================",
count+"");
Log.d("lastPos================",
lastPos+"");
}
@Override
public
void
onScrollStateChanged(AbsListView
view,
int
scrollState)
{
if(isFootLoading)
return;
if(hasFoot
&&
scrollState==SCROLL_STATE_IDLE){
isFootLoading
=
true;
onFootLoading();
}
}
/**
*
設(shè)置下拉刷新監(jiān)聽
*
*
@param
listener
*/
public
void
setOnRefreshListner(OnRefreshListner
listener)
{
//
設(shè)置下拉刷新可用
isRefreshable
=
true;
refreshListner
=
listener;
}
//執(zhí)行底部加載
public
void
onFootLoading(){
if(footLoadingListener!=null
&&
isFootLoading)
footLoadingListener.onFootLoading();
}
public
void
setOnAddFootListener(OnAddFootListener
addFootListener){
onAddFootListener
=
addFootListener;
}
//執(zhí)行添加foot
public
void
onAddFoot(){
if(onAddFootListener!=null
&&
hasFoot)
onAddFootListener.addFoot();
}
//是否添加Foot的監(jiān)聽器,如果寫在OnFootLoadingListener中會有延遲,效果不好
//應(yīng)該是先進(jìn)入添加Foot的狀態(tài),再進(jìn)入FootLoading的狀態(tài)
public
OnAddFootListener
onAddFootListener;
//是否進(jìn)入從底部加載數(shù)據(jù)的狀態(tài)的監(jiān)聽器
public
OnFootLoadingListener
footLoadingListener;
//正在加載底部數(shù)據(jù)
private
boolean
isFootLoading
=
false;
public
void
setOnFootLoadingListener(OnFootLoadingListener
footLoading){
footLoadingListener
=
footLoading;
}
/**
*
下拉刷新監(jiān)聽器
*
@author
lxj
*
*/
public
interface
OnRefreshListner
{
/**
*
下拉刷新的時候,在這里執(zhí)行獲取數(shù)據(jù)的過程
*/
void
onRefresh();
}
/**
*
上拉刷新監(jiān)聽器
*
@author
lxj
*
*/
public
interface
OnFootLoadingListener{
/**
*
這里是執(zhí)行后臺獲取數(shù)據(jù)的過程
*/
void
onFootLoading();
}
/**
*
添加Foot的監(jiān)聽器
*
@author
lxj
*
*/
public
interface
OnAddFootListener{
/**
*
這里是用戶addFootView的操作
*/
void
addFoot();
}
/**
*
底部數(shù)據(jù)加載完成,用戶需要加入一個removeFootView的操作
*/
public
void
onFootLoadingComplete(){
hasFoot
=
false;
isFootLoading
=
false;
}
/**
*
上拉刷新完成時
所執(zhí)行的操作,更改狀態(tài),隱藏head
*/
public
void
onRefreshComplete()
{
state
=
DONE;
changeHeadViewOfState();
headLastUpdate.setText("最后刷新時間:
"
+
new
Date().toLocaleString());
}
@Override
public
void
setAdapter(ListAdapter
adapter)
{
headLastUpdate.setText("最后刷新時間:
"
+
new
Date().toLocaleString());
super.setAdapter(adapter);
}
}下面是布局文件:
main.xml<?xml
version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<com.test.custom.CustomListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/listview"
/>
</LinearLayout>head.xml<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true">
<ImageView
android:id="@+id/head_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/arrow"/>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《賣報歌》教學(xué)設(shè)計及教學(xué)反思
- 《三相異步電動機的使用》設(shè)計教案
- 機場地勤車輛使用指南
- 小學(xué)科學(xué)三年級下冊教學(xué)計劃與教案
- 大型地鐵站電梯井施工合同
- 東營電動吸塵器租賃合同模板
- 員工建議與人力資源管理
- 礦山開采臨時圍墻施工協(xié)議
- 醫(yī)療器械工程師工作規(guī)范
- 招投標(biāo)文件編制法律要求詳解
- 《絲網(wǎng)印刷知識》課件
- 鐵塔基礎(chǔ)施工方案施工方案
- 有機水稻培訓(xùn)課件
- 裝維培訓(xùn)課件
- 數(shù)據(jù)分析與挖掘系統(tǒng)服務(wù)合作協(xié)議
- 安全駕駛機動車的濕滑路面
- 探究“對勾”函數(shù)的圖象與性質(zhì)+教學(xué)設(shè)計 高一上學(xué)期數(shù)學(xué)人教A版(2019)必修第一冊
- 【盒馬鮮生生鮮類產(chǎn)品配送服務(wù)問題及優(yōu)化建議分析10000字(論文)】
- 如何幫助大學(xué)生處理性別認(rèn)同和性取向問題
- 小學(xué)-信息技術(shù)試題及答案
- 高中生物必修三第一二章測試題(含答案)
評論
0/150
提交評論