关于下拉刷新/上拉加载更多的解决方案网上已经有很多了,浏览了目前主流的下拉控件比如PullToRefresh库等,第一:大多数实现库都难以进行动画和样式的自定义。第二:不能很好的兼容多种滚动控件,它们都对listView、RecyclerView等进行了不同程度的重新实现,你在项目中就得使用库提供的PullToRefreshListView、PullToRefreshRecyclerView等来代替源生的listView、RecyclerView等,这样的方式其实并不好,随着android版本的不断升级源生的listView、RecyclerView也不断加入新特性和对之前bug的修改,这使得三方实现的控件很难跟上google的节奏,当源生listView已经更新多个版本之后,三方的ListView可能还在使用低版本的实现方式。
基于如上两个原因,我开始着手开发SpringView(弹性View)
能对header/footer(头部/尾部)的样式和动画进行高度自定义,单独将header/footer独立出来,几乎可是实现任何你想要的效果,只需要继承BaseHeader/BaseFooter实现对应接口就可以。
能动态地替换header/footer,只需要设置不同的头尾即可:springView.setHeader(MyHeader());
在不重写源生控件的情况下,完美支持系统源生的listView、RecyclerView、ScrollView、WebView等,你依然使用google提供的官方控件,SpringView完全不做干涩。
使用简单,对于简单的需求甚至不用写任何代码,只需要在布局中为SpringView设置header=”@layout/…”属性即可。
SpringView是非常轻量级的实现,控件本身只有一个类
SpringView支持多点触控,可以两只手连续拖拽,你可以定制一些趣味的动画(例如demo5的仿acfun效果)
SpringView提供了2种拖拽方式(重叠和跟随),可以动态地切换
SpringView为不想去自定义头/尾的懒人提供了7种默认的实现(模仿了阿里,腾讯,美团等多种风格)如下,还会继续增加
源码及demo下载 gitbub: 下载地址
在布局文件中添加SpringView,并把你想要拖拽的控件放在SpringView中,给SpringView添加app:header=”@layout/…”属性,设置一个自己编写的头部的布局即可(footer同理):
<com.liaoinstan.springview.widget.SpringView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:header="@layout/myheader"
app:footer="@layout/myfooter">
<listView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.liaoinstan.springview.widget.SpringView>
这样,最基本的实现就完成了,运行看看吧。
当然,你也可以不再布局中设置,使用代码动态添加:
//DefaultHeader/Footer是SpringView已经实现的默认头/尾之一
//更多还有MeituanHeader、AliHeader、RotationHeader等如上图7种
springView.setHeader(new DefaultHeader(this));
springView.setFooter(new DefaultFooter(this));
如果需要处理的话,只需在代码中添加监听:
springView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
}
@Override
public void onLoadmore() {
}
});
详细的你可以看下几种默认实现的Header源码,这里只简单介绍下:
我们要做一个简单的能够记录拖拽了多少次的Header。
首先新建一个自定义头部布局,就是在RelativeLayout中放一个TextView啦:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="80dp" android:background="@drawable/view_post_comment_bg" android:layout_gravity="top">
<TextView android:layout_width="120dp" android:gravity="center" android:layout_height="wrap_content" android:text="this is TextView " android:background="#ff0000" android:textColor="#ffffff" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:id="@+id/textView" />
</RelativeLayout>
接着,新建一个MyHeader基础自BaseHeader:
public class MyHeader extends BaseHeader{
//获取Header
@Override
public View getView(LayoutInflater inflater, ViewGroup viewGroup) {}
//拖拽开始前回调
@Override
public void onPreDrag(View rootView) {}
//手指拖拽过程中不断回调,dy为拖拽的距离,可以根据拖动的距离添加拖动过程动画
@Override
public void onDropAnim(View rootView, int dy) {}
//手指拖拽过程中每次经过临界点时回调,upORdown是向上经过还是向下经过
@Override
public void onLimitDes(View rootView, boolean upORdown) {}
//拉动超过临界点后松开时回调
@Override
public void onStartAnim() {}
//头部已经全部弹回时回调
@Override
public void onFinishAnim() {}
}
注释已经很清楚了,其中必须实现的方法是getView(),将头部的View实例返回给SpringView,其余方法有需求就实现。
实现getView()方法,添加一个成员变量保存头部中的TextView:
private TextView textView;
@Override
public View getView(LayoutInflater inflater, ViewGroup viewGroup) {
View view = inflater.inflate(R.layout.header_my, viewGroup, true);
textView = (TextView)view.findViewById(R.id.textView);
return view;
}
实现onLimitDes方法,在每次经过临界点时改变TextView的内容:
private int i = 0;
@Override
public void onLimitDes(View rootView, boolean upORdown) {
i++;
textView.setText("this is TextView "+i);
}
OK,在Activity中为SpringView设置我们自定义的MyHeader就可以了,再设置一个监听器,在刷新和加载更多的时候等待1秒调用onFinishFreshAndLoad()结束刷新动作。
springView = (SpringView) findViewById(R.id.springview);
springView.setHeader(new MyHeader());
springView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
springView.onFinishFreshAndLoad();
}
}, 1000);
}
@Override
public void onLoadmore() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
springView.onFinishFreshAndLoad();
}
}, 1000);
}
});
这样就完成了一个简单的自定义Header,Footer同理。
在BaseHeader(BaseFooter同理)中默认已经实现3个方法,分别返回的是临界高度(limit hight),下拉最大高度(max height),下拉弹动高度(spring height):
如果有更加复杂的需求,需要更改这些高度的话,就在自己的Header中重写这些方法,注释已经很清楚了:
public abstract class BaseHeader implements SpringView.DragHander{
/** * 这个方法用于设置当前View的临界高度(limit hight),即拉动到多少会被认定为刷新超作,而没到达该高度则不会执行刷新 * 返回值大于0才有效,如果<=0 则设置为默认header的高度 * 默认返回0 */
@Override
public int getDragLimitHeight(View rootView) {
return 0;
}
/** * 这个方法用于设置下拉最大高度(max height),无论怎么拉动都不会超过这个高度 * 返回值大于0才有效,如果<=0 则默认600px * 默认返回0 */
@Override
public int getDragMaxHeight(View rootView) {
return 0;
}
/** * 这个方法用于设置下拉弹动高度(spring height),即弹动后停止状态的高度 * 返回值大于0才有效,如果<=0 则设置为默认header的高度 * 默认返回0 */
@Override
public int getDragSpringHeight(View rootView) {
return 0;
}
}
到这里,SpringView的使用方法基本介绍完了,后面的文章会陆续从源码介绍SpringView的实现,和自带的各种默认Header的实现。
下载请移步gitbub:
我的github
觉得不错的话,下面有个赞可以点一下:)