写着篇博客开始 ,不得不得说说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; }}
新闻热点
疑难解答