前言

原来的Android SDK中并没有下拉刷新组件,可是这个组件确实绝大多数APP必备的一个部件。好在google在v4包中出了一个SwipeRefreshLayout。可是这个组件仅仅支持下拉刷新,不支持上拉载入很多其它的操作。

因此,我们就来简单的扩展一下这个组件以实现上拉下载的目的。

基本原理

上拉载入或者说滚动究竟部时自己主动载入,都是通过推断是否滚动到了ListView或者其它View的底部,然后触发对应的操作,这里我们以ListView来说明。因此我们须要在监听ListView的滚动事件,当ListView滚动究竟部时自己主动触发载入操作;可是当用户支持手指滑动屏幕,没有滚动时,我们也须要让它载入,因此这样的情形就是上拉载入很多其它。所以我们须要在触摸事件里面进行推断,假设到了底部,且用户是上拉操作,那么运行载入很多其它。很多其它关于下拉刷新、上拉载入请參考打造通用的Android下拉刷新组件(适用于ListView、GridView等各类View)
时间有限,直接上代码吧。

实现代码

/**
* 继承自SwipeRefreshLayout,从而实现滑动究竟部时上拉载入很多其它的功能.
*
* @author mrsimple
*/
public class RefreshLayout extends SwipeRefreshLayout implements OnScrollListener { /**
* 滑动到最以下时的上拉操作
*/ private int mTouchSlop;
/**
* listview实例
*/
private ListView mListView; /**
* 上拉监听器, 到了最底部的上拉载入操作
*/
private OnLoadListener mOnLoadListener; /**
* ListView的载入中footer
*/
private View mListViewFooter; /**
* 按下时的y坐标
*/
private int mYDown;
/**
* 抬起时的y坐标, 与mYDown一起用于滑动究竟部时推断是上拉还是下拉
*/
private int mLastY;
/**
* 是否在载入中 ( 上拉载入很多其它 )
*/
private boolean isLoading = false; /**
* @param context
*/
public RefreshLayout(Context context) {
this(context, null);
} public RefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mListViewFooter = LayoutInflater.from(context).inflate(R.layout.listview_footer, null,
false);
} @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom); // 初始化ListView对象
if (mListView == null) {
getListView();
}
} /**
* 获取ListView对象
*/
private void getListView() {
int childs = getChildCount();
if (childs > 0) {
View childView = getChildAt(0);
if (childView instanceof ListView) {
mListView = (ListView) childView;
// 设置滚动监听器给ListView, 使得滚动的情况下也能够自己主动载入
mListView.setOnScrollListener(this);
Log.d(VIEW_LOG_TAG, "### 找到listview");
}
}
} /*
* (non-Javadoc)
* @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction(); switch (action) {
case MotionEvent.ACTION_DOWN:
// 按下
mYDown = (int) event.getRawY();
break; case MotionEvent.ACTION_MOVE:
// 移动
mLastY = (int) event.getRawY();
break; case MotionEvent.ACTION_UP:
// 抬起
if (canLoad()) {
loadData();
}
break;
default:
break;
} return super.dispatchTouchEvent(event);
} /**
* 能否够载入很多其它, 条件是到了最底部, listview不在载入中, 且为上拉操作.
*
* @return
*/
private boolean canLoad() {
return isBottom() && !isLoading && isPullUp();
} /**
* 推断是否到了最底部
*/
private boolean isBottom() { if (mListView != null && mListView.getAdapter() != null) {
return mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - 1);
}
return false;
} /**
* 是否是上拉操作
*
* @return
*/
private boolean isPullUp() {
return (mYDown - mLastY) >= mTouchSlop;
} /**
* 假设到了最底部,并且是上拉操作.那么运行onLoad方法
*/
private void loadData() {
if (mOnLoadListener != null) {
// 设置状态
setLoading(true);
//
mOnLoadListener.onLoad();
}
} /**
* @param loading
*/
public void setLoading(boolean loading) {
isLoading = loading;
if (isLoading) {
mListView.addFooterView(mListViewFooter);
} else {
mListView.removeFooterView(mListViewFooter);
mYDown = 0;
mLastY = 0;
}
} /**
* @param loadListener
*/
public void setOnLoadListener(OnLoadListener loadListener) {
mOnLoadListener = loadListener;
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
// 滚动时到了最底部也能够载入很多其它
if (canLoad()) {
loadData();
}
} /**
* 载入很多其它的监听器
*
* @author mrsimple
*/
public static interface OnLoadListener {
public void onLoad();
}
}
listview_footer.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/umeng_comm_comments_bg"
android:gravity="center"
android:paddingBottom="8dip"
android:paddingTop="5dip" > <ProgressBar
android:id="@+id/pull_to_refresh_load_progress"
style="@android:style/Widget.ProgressBar.Small.Inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:paddingRight="100dp"
android:indeterminate="true" /> <TextView
android:id="@+id/pull_to_refresh_loadmore_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="5dip"
android:text="@string/load"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/darker_gray"
android:textSize="14sp"
android:textStyle="bold" /> </RelativeLayout>

使用演示样例

refresh.xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<myview.RefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" > <ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView> </myview.RefreshLayout>

activity中的使用 : 

/**
* @author mrsimple
*/
public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.refresh); // 模拟一些数据
final List<String> datas = new ArrayList<String>();
for (int i = 0; i < 20; i++) {
datas.add("item - " + i);
} // 构造适配器
final BaseAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
datas);
// 获取listview实例
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter); // 获取RefreshLayout实例
final RefreshLayout myRefreshListView = (RefreshLayout)
findViewById(R.id.swipe_layout); // 设置下拉刷新时的颜色值,颜色值须要定义在xml中
myRefreshListView
.setColorScheme(R.color.umeng_comm_text_topic_light_color,
R.color.umeng_comm_yellow, R.color.umeng_comm_green,
R.color.umeng_comm_linked_text);
// 设置下拉刷新监听器
myRefreshListView.setOnRefreshListener(new OnRefreshListener() { @Override
public void onRefresh() { Toast.makeText(MainActivity.this, "refresh", Toast.LENGTH_SHORT).show(); myRefreshListView.postDelayed(new Runnable() { @Override
public void run() {
// 更新数据
datas.add(new Date().toGMTString());
adapter.notifyDataSetChanged();
// 更新完后调用该方法结束刷新
myRefreshListView.setRefreshing(false);
}
}, 1000);
}
}); // 载入监听器
myRefreshListView.setOnLoadListener(new OnLoadListener() { @Override
public void onLoad() { Toast.makeText(MainActivity.this, "load", Toast.LENGTH_SHORT).show(); myRefreshListView.postDelayed(new Runnable() { @Override
public void run() {
datas.add(new Date().toGMTString());
adapter.notifyDataSetChanged();
// 载入完后调用该方法
myRefreshListView.setLoading(false);
}
}, 1500); }
});
} }

效果图

github链接 : 下拉刷新库
演示样例在android_my_pull_demoproject中。进入demo后点击最后一个button查看效果就可以。注意,在刷新和载入时,须要有一定的延时才干看到效果,这里我们用postDelay来模拟网络请求等延时操作,否则将看不到载入效果。这里仅仅提供一个实现思路,代码不太完好,须要用的请自行完好并測试。
注意
假设出现HeaderViewListAdapter转换异常,那么请使用RefreshLvLayout中的setAdapter函数为ListView设置Adapter,
这样能够确保在设置Adapter之前已经加入了Footer。

让Android Support V4中的SwipeRefreshLayout支持上拉载入很多其它的更多相关文章

  1. Android利用V4包中的SwipeRefreshLayout实现上拉加载

    基本原理 上拉加载或者说滚动到底部时自动加载,都是通过判断是否滚动到了ListView或者其他View的底部,然后触发相应的操作,这里我们以 ListView来说明.因此我们需要在监听ListView ...

  2. Android实现RecyclerView的下拉刷新和上拉载入很多其它

    需求 先上效果图, Material Design风格的下拉刷新和上拉载入很多其它. 源代码地址(欢迎star) https://github.com/studychen/SeeNewsV2 假设对于 ...

  3. 使用SwipeRefreshLayout和RecyclerView实现仿“简书”下拉刷新和上拉载入很多其它

    一.概述 本篇博客介绍的是怎样使用SwipeRefreshLayout和RecyclerView实现高仿简书Android端的下拉刷新和上拉载入很多其它的效果. 依据效果图能够发现,本案例实现了例如以 ...

  4. Android下拉刷新上拉载入控件,对全部View通用!

    转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/38868463 前面写过一篇关于下拉刷新控件的博客下拉刷新控件终结者:Pull ...

  5. Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)

    转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉载入,网上的Demo太多太多了,这 ...

  6. 在布局中使用android.support.v4.app.Fragment的注意事项

    1.Activity必须继承android.support.v4.app.FragmentActivity 2.fragment标签的name属性必须是完全限定包名,如下: <LinearLay ...

  7. Android studio中怎么导入android.support.v4包

    Android studio中怎么导入android.support.v4包 1.File点击选择projectStructure选择对应的APP然后点击Dependencies 2.点击+号,点击第 ...

  8. android.support.v4.app.Fragment和android.app.Fragment区别

    1.最低支持版本不同 android.app.Fragment 兼容的最低版本是android:minSdkVersion="11" 即3.0版 android.support.v ...

  9. Android Support v4,v7,v13

    Android Support v4 是最早(2011年4月份)实现的库.用在Android1.6 (API lever 4)或者更高版本之上.它包含了相对V4, V13大的多的功能. 例如:Frag ...

随机推荐

  1. css 行内元素设置宽高

    有2中实现方法: 1.设置display:block   inline-block,使其width属性生效 2.如果设置float:left | right, 使其width属性生效. (浮动)使得指 ...

  2. defaultView and parentWindow

    defaultView     只读的 which is used to represent the currently rendered view of the document 返回的值通常是包含 ...

  3. 一般处理程序获取Session方式

    今天写程序得时候遇到了一个问题:ajax在对ashx进行请求时如果按照 context.Request方式直接来获取值得话获取到得是空值,因此去网上搜了一下问题.现记录如下: ashx获取sessio ...

  4. Ajax跨域 CROS处理

    Ajax跨域方法有多种 这里介绍CROS跨域的实际案例 场景:A域名 请求 B域名: 暂且 A为客户端 B为服务端: 请求的服务端必须自己能控制 或者服务器端头部已经添加 Access-Control ...

  5. MyBatis《2》

    MyBatis入参考文档:http://mybatis.org/mybatis-3/zh/   1.properties 属性 1.在MyBatis配置文件中引用属性文件     MyBatis允许在 ...

  6. 开源纯C#工控网关+组态软件(六)图元组件

    一.   图元概述 图元是构成人机界面的基本单元.如一个个的电机.设备.数据显示.仪表盘,都是图元.构建人机界面的过程就是铺排.挪移.定位图元的过程. 图元设计是绘图和编码的结合.因为图元不仅有显示和 ...

  7. .net 系列:事件和委托

    在.net 的世界里,离不开委托和事件,其实理解透了后很简单,总结了一下分为5步:   1)定义委托   public delegate void RevicedEventHandler(object ...

  8. 初识CC_MVPMatrix

    初识CC_MVPMatrix CC_MVPMatrix是一个mat4类型的uniform,在shader代码被编译之前,它由cocos2d-x框架插入进来的. bool GLProgram::comp ...

  9. swaggerui在asp.net web api core 中的应用

    Swaggerui 可以为我们的webapi提供美观的在线文档,如下图: 实现步骤: NuGet Packages  Install-Package Swashbuckle.AspNetCore 在s ...

  10. wkwebview加载本地html的要点

    项目中有些页面,我采用了html页面开发,然后用wkwebview加载的设计.在加载过程中遇见了一些问题,在这里进行一些记载和讨论.如有不同意见欢迎进行评论沟通. 问题时候这样的: 在webview的 ...