寫著篇博客開始 ,不得不得發(fā)發(fā)牢騷了。為什么你搞一個下拉刷新,你為什么不直接再加一個上拉加載呢? 我們都很藍(lán)瘦啊,開心的用上了原生的swiperefreshlayout 但是萬萬沒想到 人家只有下拉刷新 沒有上拉加載。
他沒有加怎么辦? 我們自己加啊。那么牛逼已經(jīng)吹出去了 ,接下來就是教大家如何添加上拉加載。下拉刷新的話其實(shí)很簡單我就簡單貼上代碼
setColorSchemeResources(R.color.orange, R.color.green,
R.color.holo_red_light); // 進(jìn)度動畫顏色
setProgressBackgroundColorSchemeResource(
R.color.light_gray); // 進(jìn)度背景顏色
就加上上面的配置下顏色就行。那么如何添加上拉加載呢
首先 大家要明白什么時(shí)候出現(xiàn)上拉加載 就是listview 滾動到底部的時(shí)候添加上拉加載。如何判斷到了底部呢。網(wǎng)上你查的很多都是這樣的?
lv.getLastVisiblePosition()==lv.getAdapter().getCount()-1
那么這樣到底行不行? 答案是行 但是有些不盡人意 因?yàn)槿绻愕臈l目夠高的話你會發(fā)現(xiàn),最后一個條目剛露頭 你就開始加載了 ,但是用戶完全懵逼不知道到底了。所以如何在真正的滾到底部的時(shí)候加載呢。就是加一個判斷最后一個條目的bottom 如果等于 listview 的高度那么肯定是滾動到底部了吧所以最后判斷是這樣的
if(lv.getLastVisiblePosition()==lv.getAdapter().getCount()-1 //最后一個條目
&&!isLoading // 之前沒有執(zhí)行加載 防止重新加載
&&isPullUp() // 是上拉操作 根據(jù)touchevent判斷y 坐標(biāo)即可){
ViewlastVisibleItemView=lv.getChildAt(lv.getChildCount() - 1);
if (lastVisibleItemView != null && lastVisibleItemView.getBottom() == lv.getHeight()) {
// 執(zhí)行上拉加載更多
}
}
這樣 上拉加載的觸發(fā)條件我們就知道了。那么接下來就是 在觸發(fā)的時(shí)候?yàn)閘istview 添加一個footer 就行了。 然后在加載完畢移除這個footer 就完事了 ,那這么說是不是很簡單的完成了呢 我想說基本的上拉加載你知道這些就可以完成了。那么很多上拉加載的都是一邊網(wǎng)上拉一邊改變底部加載的高度是怎么實(shí)現(xiàn)的呢? 我簡單說下原理因?yàn)槲蚁勇闊]做 (鄙視自己一秒鐘)其實(shí)就是先添加那個footer 然后設(shè)置他的margintop 為一個負(fù)值 這樣他可以隱藏起來, 當(dāng)我們滾動到底部的時(shí)候 監(jiān)聽手機(jī)移動事件根據(jù)那個y變化 ,動態(tài)改變footer 的margin,最后當(dāng)footer 完全顯示時(shí) 執(zhí)行加載動畫?!∥抑苯淤N上最后的代碼
* Created by sunyeyu 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);
intchilds=getChildCount();
if (childs>0) {
if (getChildAt(1)instanceof ListView) {
if(lv==null) { // 要判斷為空時(shí)才進(jìn)行下面的操作 因?yàn)槊看萎?dāng)下拉刷新的時(shí)候 omeasure 是會多次調(diào)用的 所以避免重復(fù)調(diào)用
lv= (ListView) getChildAt(1);// 這里我們是用的1 因?yàn)? 是那個下拉刷新的源圈
lv.setAdapter(ba);
lv.setOnScrollListener(this);
lv.setOnItemClickListener(oic);
footer=View.inflate(getContext(),footerLayoutId,null);
}
}
}
}
public MySwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArrayta=context.obtainStyledAttributes(attrs, R.styleable.MySwipeRefreshLa yout);// 我這里用了自定義屬性來添加footer 的布局
footerLayoutId=ta.getResourceId(R.styleable.MySwipeRefreshLayout_footerLayoutI d,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) 因?yàn)檫@ 時(shí)候 lv 還沒有被賦值 這時(shí)候調(diào)用時(shí)會報(bào)空指針的。
}
@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()){
ViewlastVisibleItemView=lv.getChildAt(lv.getChildCount() - 1);
if (lastVisibleItemView != null && lastVisibleItemView.getBottom() == lv.getHeight()) {
Load();
}
}
}
private boolean isPullUp() {
if(upY
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); // 進(jìn)度動畫顏色
setProgressBackgroundColorSchemeResource(
R.color.light_gray); // 進(jìn)度背景顏色
setOnRefreshListener(ol);
}
BaseAdapter ba;
public void setAdapter(BaseAdapter ba){
this.ba=ba;
}
/** 刷新結(jié)束 取消下拉刷新 */
public void setHeader(boolean isHeader){
setRefreshing(isHeader);
}
/**
* 加載更多的監(jiān)聽器
*/
public interface OnLoadMoreListener {
void onLoad();
}
OnLoadMoreListener mOnLoadListener;
public void setOnLoadListener(OnLoadMoreListener loadListener) {
mOnLoadListener=loadListener;
}
}