4.實現(xiàn)自定義ListView的下拉刷新皆串、上拉加載更多

效果圖

下拉刷新

由于整個布局帶有兩個Header,所以這里自己寫了一個類來繼承ListView去實現(xiàn)它的方法屉栓,并根據(jù)ontouch里面滑動的參數(shù)來判斷什么時候顯示

一:下拉刷新

1.由于我的輪播的那個圖,已經(jīng)是頭部文件了,所以我的下拉刷新是在自定義的ListView中添加的脚草,

private void initHeaderView(){

mMMHeaderView = View.inflate(getContext(), R.layout.pull_to_refresh,null);

/*這里的mMMHeaderView就是下拉刷新弄砍,ListView先加載這個布局,之后在引用ListView的地方加載第二個Header

*/

? ? this.addHeaderView(mMMHeaderView);

? ? //找到各個布局

? ? mIv_listheader =mMMHeaderView.findViewById(R.id.iv_listheader);

? ? mPb_listheader =mMMHeaderView.findViewById(R.id.pb_listheader);

? ? mTv_listheader_title =mMMHeaderView.findViewById(R.id.tv_listheader_title);

? ? tv_listheader_data =mMMHeaderView.findViewById(R.id.tv_listheader_data);

? ? // 在生成布局時得到布局的寬高

? ? mMMHeaderView.measure(0,0);

? ? mMHeaderViewHeight =mMMHeaderView.getMeasuredHeight();

? ? mMMHeaderView.setPadding(0,-mMHeaderViewHeight,0,0);

? ? initAnimation();

}


2.根據(jù)滑動來判斷當前的刷新的狀態(tài)撼唾,來設置頭布局的顯示與隱藏廉邑,重寫onTouchEvent方法

private int mStartY = -1;

//下拉刷新

public static final int STATE_PULL_TO_REFRESH =1;

//釋放刷新

public static final int STATE_RELEASE_TO_REFRESH =2;

//正在刷新

public static final int STATE_REFRESHING =3;

//當前刷新的欄的狀態(tài)

public int currentstate =STATE_PULL_TO_REFRESH;


@Override

public boolean onTouchEvent(MotionEvent ev) {

switch (ev.getAction()){

case MotionEvent.ACTION_DOWN:

//得到屏幕滑動的初始y值

mStartY = (int) ev.getY();

break;

? ? ? ? case MotionEvent.ACTION_MOVE:

//如果當前處于刷新狀態(tài),則直接break,不進行下列操作

if(currentstate ==STATE_REFRESHING){

break;

? ? ? ? ? ? }

//防止ListView沒有捕獲到滑動開始時的點擊事件

if(mStartY == -1){

mStartY = (int)ev.getY();

? ? ? ? ? ? }

int endy = (int)ev.getY();

? ? ? ? ? ? //dy 為移動的距離倒谷,如果向下滑動蛛蒙,則dy大于0,當前的頭布局已經(jīng)設置padding為 負的布局高度渤愁,再用正的

//減去布局高度牵祟,則得到的隱藏值將會縮小

? ? ? ? ? ? int dy = endy -mStartY;

? ? ? ? ? ? Log.i("TAG","dy:"+dy+"? endy:"+endy);

? ? ? ? ? ? int firstVisiblePosition = getFirstVisiblePosition();

//2.讓刷新布局跟隨手指移動 ,當在頂部的時候抖格,向下拉這用滑動的距離減去刷新布局的高度诺苹,則將刷新布更改位置

? ? ? ? ? ? if(dy >0 && firstVisiblePosition ==0){

int padding = dy -mMHeaderViewHeight;

? ? ? ? ? ? ? ? mMMHeaderView.setPadding(0,padding,0,0);

? ? ? ? ? ? ? ? if(padding >0 &¤tstate !=STATE_RELEASE_TO_REFRESH){

currentstate =STATE_RELEASE_TO_REFRESH;

? ? ? ? ? ? ? ? ? ? refreshState();

? ? ? ? ? ? ? ? }else if(padding <0 &¤tstate !=STATE_PULL_TO_REFRESH){

currentstate =STATE_PULL_TO_REFRESH;

? ? ? ? ? ? ? ? ? ? refreshState();

? ? ? ? ? ? ? ? }

return true;

? ? ? ? ? ? }

break;

? ? ? ? case MotionEvent.ACTION_UP:

mStartY = -1;

? ? ? ? ? ? // 當松開布局時咕晋,判斷當前狀態(tài),將布局隱藏或者顯示

? ? ? ? ? ? if(currentstate ==STATE_RELEASE_TO_REFRESH){

currentstate =STATE_REFRESHING;

? ? ? ? ? ? ? ? refreshState();

? ? ? ? ? ? ? ? mMMHeaderView.setPadding(0,0,0,0);

? ? ? ? ? ? }else if(currentstate ==STATE_PULL_TO_REFRESH){

mMMHeaderView.setPadding(0,-mMHeaderViewHeight,0,0);

? ? ? ? ? ? }

break;

? ? ? ? default:

break;

? ? }

return super.onTouchEvent(ev);

}

// 這個方法根據(jù)滑動的狀態(tài)去更新布局的信息

private void refreshState() {

switch (currentstate){

case STATE_PULL_TO_REFRESH:

mTv_listheader_title.setText("下拉刷新");

? ? ? ? ? ? mPb_listheader.setVisibility(View.INVISIBLE);

? ? ? ? ? ? mIv_listheader.setVisibility(View.VISIBLE);

? ? ? ? ? ? mIv_listheader.startAnimation(mDownanimation);

break;

? ? ? ? case STATE_REFRESHING:

mIv_listheader.clearAnimation();

? ? ? ? ? ? mTv_listheader_title.setText("正在刷新...");

? ? ? ? ? ? mPb_listheader.setVisibility(View.VISIBLE);

? ? ? ? ? ? mIv_listheader.setVisibility(View.INVISIBLE);

? ? ? ? ? ? //調(diào)用刷新的方法

? ? ? ? ? ? mListener.onrefresh();

break;

? ? ? ? case STATE_RELEASE_TO_REFRESH:

mTv_listheader_title.setText("釋放刷新");

? ? ? ? ? ? mPb_listheader.setVisibility(View.INVISIBLE);

? ? ? ? ? ? mIv_listheader.setVisibility(View.VISIBLE);

? ? ? ? ? ? mIv_listheader.startAnimation(mUpanimation);

break;

? ? ? ? default:

break;

? ? }

}

3.定義接口和方法讓外部回調(diào)

// 3.1 這個方法是刷新完成后調(diào)用收奔,隱藏布局

public void setRefreshComplement() {

mMMHeaderView.setPadding(0,-mMHeaderViewHeight,0,0);

? ? currentstate =STATE_PULL_TO_REFRESH;

? ? mTv_listheader_title.setText("下拉刷新");

? ? mPb_listheader.setVisibility(View.INVISIBLE);

? ? mIv_listheader.setVisibility(View.VISIBLE);

? ? mIv_listheader.startAnimation(mDownanimation);

}

// 定義解控供外部調(diào)用

public interface OnRefreshListener{

void onrefresh();

}

private ?OnRefreshListenermListener mListener;

//外部布局設置刷新的方法

public void setOnRefreshListener(OnRefreshListener listener){

this.mListener = listener;

}

4.在外部調(diào)用設置接口的方法掌呜,調(diào)用刷新的方法

mlv_news.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {

@Override

? ? public void onrefresh() {

getDataFromServer();

? ? }

});

//當請求數(shù)據(jù)成功,并解析出來后調(diào)用刷新完成的方法坪哄,隱藏布局

x.http().get(params, new Callback.CommonCallback() {

@Override

? ? public void onSuccess(String result) {

processData(result);

? ? ? ? // 保存緩存

? ? ? ? PrefUtils.setString(mactivity,mUri,result);

? ? ? ? mlv_news.setRefreshComplement();

? ? }

}


二:上拉加載更多

2.1:定義一個上拉加載的布局质蕉,我的是pull_to_refresh_footer.xml

<?xml version="1.0" encoding="utf-8"?>

? ? xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

? ? android:layout_height="wrap_content"

? ? android:gravity="center"

? ? >

? ? ? ? android:id="@+id/pb_listheader"

? ? ? ? android:layout_width="wrap_content"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:indeterminateDrawable="@drawable/custom_progress"

? ? ? ? android:visibility="visible"

? ? ? ? />

? ? ? ? android:layout_marginLeft="5dp"

? ? ? ? android:layout_width="wrap_content"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:text="加載更多"

? ? ? ? />

</LinearLayout>

2.2:為footerview初始化,找到布局损姜,并將ListView加入FooterView,這里讓繼承ListView的布局實現(xiàn)OnScrollListener接口

private void initFooterView(){

mMFooterView = View.inflate(getContext(),R.layout.pull_to_refresh_footer,null);

? ? this.addFooterView(mMFooterView);

? ? mMFooterView.measure(0,0);

? ? mFooterViewHeight =mMFooterView.getMeasuredHeight();

? ? mMFooterView.setPadding(0,-mMHeaderViewHeight,0,0);

? ? this.setOnScrollListener(this);

}

2.3在自己定義的接口中定義加載更多的方法饰剥,其中l(wèi)oadmore(),就是供外部加載更多的方法/***

@param view

* @param scrollState

* 在滑動的監(jiān)聽中更新加載更多的布局的位置,其中 isLoadMore是為了防止用戶在加載更多的時候再次滑動摧阅,造成數(shù)據(jù)得重復

* 加載汰蓉,其中setSelection(getCount() -1)是讓加載更多時直接全部拖出,不然用戶有時滑至底部不知道下滑加載更多,調(diào)用

* 讓監(jiān)聽執(zhí)行l(wèi)oadmore方法

*

*/

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

if(scrollState ==SCROLL_STATE_IDLE){

int lastVisiblePosition = getLastVisiblePosition();

? ? ? ? if(lastVisiblePosition == getCount() -1 && !isLoadMore){

isLoadMore =true;

? ? ? ? ? ? mMFooterView.setPadding(0,0,0,0);

? ? ? ? ? ? //將listview的位置設置到最后一個item布局

? ? ? ? ? ? setSelection(getCount() -1);

? ? ? ? ? ? mListener.loadmore();

? ? ? ? }

}

}


2.4:在外部調(diào)用執(zhí)行具體的loadmore()方法

//獲取到加載更多的url棒卷,如果存在下一個頁面的Url則加載顾孽,否則賦值為null

String loadmore = newTabBean.data.more;

if(!TextUtils.isEmpty(loadmore)){

mLoadmoreurl = ConstantValues.SERVER_URL+loadmore;

}else {

mLoadmoreurl =null;

}

通過判斷路徑是否為空來調(diào)用getDataMoreFromServer()方法,去服務器請求更多的數(shù)據(jù)

@Override

public void loadmore() {

if(mLoadmoreurl !=null) {

getDataMoreFromServer();

? ? }else{

Toast.makeText(mactivity,"沒有更多數(shù)據(jù)了",Toast.LENGTH_SHORT).show();

? ? ? ? mlv_news.setRefreshComplement(false);

? ? }

}

調(diào)用解析數(shù)據(jù)方法是比规,傳入一個

private void getDataMoreFromServer(){

RequestParams params =new RequestParams(mLoadmoreurl);

? ? x.http().get(params, new Callback.CommonCallback() {

@Override

? ? ? ? public void onSuccess(String result) {

processData(result,true);

? ? ? ? ? ? mlv_news.setRefreshComplement(false);

? ? ? ? }

@Override

? ? ? ? public void onError(Throwable ex, boolean isOnCallback) {

Toast.makeText(mactivity,"獲取數(shù)據(jù)失敗",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? mlv_news.setRefreshComplement(false);

? ? ? ? }

@Override

? ? ? ? public void onCancelled(CancelledException cex) {

}

@Override

? ? ? ? public void onFinished() {

}

});

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末若厚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜒什,更是在濱河造成了極大的恐慌测秸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灾常,死亡現(xiàn)場離奇詭異霎冯,居然都是意外死亡,警方通過查閱死者的電腦和手機钞瀑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門沈撞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雕什,你說我怎么就攤上這事缠俺。” “怎么了贷岸?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵壹士,是天一觀的道長。 經(jīng)常有香客問我凰盔,道長墓卦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任户敬,我火速辦了婚禮落剪,結(jié)果婚禮上睁本,老公的妹妹穿的比我還像新娘。我一直安慰自己忠怖,他們只是感情好呢堰,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凡泣,像睡著了一般枉疼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鞋拟,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天骂维,我揣著相機與錄音,去河邊找鬼贺纲。 笑死航闺,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的猴誊。 我是一名探鬼主播潦刃,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼懈叹!你這毒婦竟也來了乖杠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤澄成,失蹤者是張志新(化名)和其女友劉穎胧洒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體墨状,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡略荡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了歉胶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡巴粪,死狀恐怖通今,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肛根,我是刑警寧澤辫塌,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站派哲,受9級特大地震影響臼氨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芭届,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一储矩、第九天 我趴在偏房一處隱蔽的房頂上張望感耙。 院中可真熱鬧,春花似錦持隧、人聲如沸即硼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽只酥。三九已至,卻和暖如春呀狼,著一層夾襖步出監(jiān)牢的瞬間裂允,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工哥艇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绝编,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓她奥,卻偏偏與公主長得像瓮增,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子哩俭,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容