寫著篇博客開始 ,不得不得說說google 的開發人員。為什么你搞一個下拉刷新,你為什么不直接再加一個上拉加載呢? 我們都很藍瘦啊,開心的用上了原生的swiperefreshlayout 但是萬萬沒想到 人家只有下拉刷新 沒有上拉加載。
他沒有加怎么辦? 我們自己加啊。那么牛逼已經吹出去了 ,接下來就是教大家如何添加上拉加載。下拉刷新的話其實很簡單我就簡單貼上代碼
setColorSchemeResources(R.color.orange, R.color.green, R.color.holo_red_light); // 進度動畫顏色 setPRogressBackgroundColorSchemeResource( R.color.light_gray); // 進度背景顏色就加上上面的配置下顏色就行。那么如何添加上拉加載呢首先 大家要明白什么時候出現上拉加載 就是listview 滾動到底部的時候添加上拉加載。如何判斷到了底部呢。網上你查的很多都是這樣的?
lv.getLastVisiblePosition()==lv.getAdapter().getCount()-1那么這樣到底行不行? 答案是行 但是有些不盡人意 因為如果你的條目夠高的話你會發現,最后一個條目剛露頭 你就開始加載了 ,但是用戶完全懵逼不知道到底了。
所以如何在真正的滾到底部的時候加載呢。就是加一個判斷最后一個條目的bottom 如果等于 listview 的高度那么肯定是滾動到底部了吧所以最后判斷是這樣的
if(lv.getLastVisiblePosition()==lv.getAdapter().getCount()-1 //最后一個條目&&!isLoading // 之前沒有執行加載 防止重新加載&&isPullUp() // 是上拉操作 根據touchevent判斷y 坐標即可){ View lastVisibleItemView = lv.getChildAt(lv.getChildCount() - 1); if (lastVisibleItemView != null && lastVisibleItemView.getBottom() == lv.getHeight()) { // 執行上拉加載等多 } } 這樣 上拉加載的觸發條件我們就知道了。那么接下來就是 在觸發的時候為listview 添加一個footer 就行了。 然后在加載完畢移除這個footer 就完事了 ,那這么說是不是很簡單的完成了呢 我想說基本的上拉加載你知道這些就可以完成了。那么很多上拉加載的都是一邊網上拉一邊改變底部加載的高度是怎么實現的呢? 我簡單說下原理因為我嫌麻煩沒做 (鄙視自己一秒鐘)其實就是先添加那個footer 然后設置他的margintop 為一個負值 這樣他可以隱藏起來, 當我們滾動到底部的時候 監聽手機移動事件根據那個y變化 ,動態改變footer 的margin,最后當footer 完全顯示時 執行加載動畫。廢話說了很多我直接貼上最后的代碼package com.nh.cp.common.widet;import android.content.Context;import android.content.res.TypedArray;import android.support.v4.widget.SwipeRefreshLayout;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.AbsListView;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.ListView;import com.nh.cp.R;/** * Created by ouyangyu on 2017-02-28 . */public class MySwipeRefreshLayout extends SwipeRefreshLayout implements AbsListView.OnScrollListener { private ListView lv; int footerLayoutId; private boolean isLoading; private float downY; private float upY; private View footer; private boolean isRefreshFoot; public MySwipeRefreshLayout(Context context) { super(context); init(); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childs = getChildCount(); if (childs > 0) { if (getChildAt(1)instanceof ListView) { if(lv==null) { // 要判斷為空時才進行下面的操作 因為每次當下拉刷新的時候 omeasure 是會多次調用的 所以避免重復調用 lv = (ListView) getChildAt(1);// 這里我們是用的1 因為0 是那個下拉刷新的源圈 lv.setAdapter(ba); lv.setOnScrollListener(this); lv.setOnItemClickListener(oic); footer= View.inflate(getContext(),footerLayoutId,null); } } } } public MySwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.MySwipeRefreshLayout);// 我這里用了自定義屬性來添加footer 的布局 footerLayoutId=ta.getResourceId(R.styleable.MySwipeRefreshLayout_footerLayoutId,0); // 得到footer布局id 加載出view if(footerLayoutId==0){ Log.e("MySwipeRefreshLayout","沒有在xml配置footer的布局id屬性"); } init(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: downY=ev.getRawY(); break; case MotionEvent.ACTION_UP: upY=ev.getRawY(); canLoadMore();// 抬起是判斷是否可以顯示上拉加載 } return super.dispatchTouchEvent(ev); } AdapterView.OnItemClickListener oic; public void setListItemClickListener(AdapterView.OnItemClickListener oic){ this.oic=oic; // 我這里并沒有直接用 lv.setonitemclicklistener(oic) 因為這時候 lv 還沒有被賦值 這時候調用時會報空指針的。 } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { canLoadMore(); } private void canLoadMore() { if(lv.getLastVisiblePosition()==lv.getAdapter().getCount()-1&& !isLoading&&isPullUp()){ View lastVisibleItemView = lv.getChildAt(lv.getChildCount() - 1); if (lastVisibleItemView != null && lastVisibleItemView.getBottom() == lv.getHeight()) { Load(); } } } private boolean isPullUp() { if(upY<downY){ return true; } return false; } private void Load(){ isLoading=true; lv.addFooterView(footer); if(mOnLoadListener!=null){ mOnLoadListener.onLoad(); } } public void setFooter(boolean hasRefreshFoot){ if(!hasRefreshFoot){ lv.removeFooterView(footer); isLoading=false; } } public void setHeaderListener(OnRefreshListener ol){ setColorSchemeResources(R.color.orange, R.color.green, R.color.holo_red_light); // 進度動畫顏色 setProgressBackgroundColorSchemeResource( R.color.light_gray); // 進度背景顏色 setOnRefreshListener(ol); } BaseAdapter ba; public void setAdapter(BaseAdapter ba){ this.ba=ba; } /** 刷新結束 取消下拉刷新 */ public void setHeader(boolean isHeader){ setRefreshing(isHeader); } /** * 加載更多的監聽器 */ public interface OnLoadMoreListener { void onLoad(); } OnLoadMoreListener mOnLoadListener; public void setOnLoadListener(OnLoadMoreListener loadListener) { mOnLoadListener= loadListener; }}
新聞熱點
疑難解答