SpringView
android开发游记:SpringView 下拉刷新的高效解决方案,定制你自己风格的拖拽页面
SpringView 是一个提供了上下拖拽的功能组件,能够进行高度自定义,实现各种下拉\上拉动画效果,demo里实现了:仿阿里旅行、仿美团,仿QQ下拉刷红包,仿acfun等,完全兼容源生控件如ListView、RecyclerView、ScrollView、WebView等,使用简单,轻易定制自己风格的拖拽页面。
SpringView 单独将头部/尾部独立出来,几乎可以实现任何你想要的效果,只需要继承BaseHeader(或Footer)实现接口
SpringView 能在运行时动态地替换头部/尾部,只需要设置不同的头尾即可:springView.setHeader(MyHeader());
SpringView 支持多点触控,可以两只手连续拖拽,你可以定制一些非常有趣的效果(例如demo5)
SpringView 提供了2种拖拽方式(重叠和跟随),可以动态地切换
SpringView 为不想去自定义头/尾的懒人提供了7种默认的实现(模仿了阿里,腾讯,美团等多种风格)如下,还会继续增加
SpringView 支持和 AppBarLayout 联动
如何使用 SpringView
依赖
dependencies {
//SpringView核心库 (只包含DefaultHeader/Footer)
implementation 'com.liaoinstan.springview:library:1.7.0'
//以下是各个风格的Header/Footer,选择自己喜欢的引入
implementation 'com.liaoinstan.springview:AcfunHeader:1.7.0' //AcFun风格 (header and footer)
implementation 'com.liaoinstan.springview:AliHeader:1.7.0' //阿里旅行风格 (header and footer)
implementation 'com.liaoinstan.springview:MeituanHeader:1.7.0' //美团风格 (header and footer)
implementation 'com.liaoinstan.springview:RotationHeader:1.7.0' //齿轮机械风格 (header and footer)
implementation 'com.liaoinstan.springview:WeixinHeader:1.7.0' //微信小程序header(只有header)
implementation 'com.liaoinstan.springview:DuHeader:1.7.0' //'毒'App header(只有header)
}
在布局文件中添加SpringView,注意SpringView和ScrollView有同样的限制:只能有一个子元素:
<com.liaoinstan.springview.widget.SpringView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:header="@layout/myheader"
app:footer="@layout/myfooter">
<ListView RecyclerView ScrollView or others
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.liaoinstan.springview.widget.SpringView>
当然,你也可以不在布局中设置header\footer,使用代码动态添加:
springView.setHeader(new DefaultHeader(this));
springView.setFooter(new DefaultFooter(this));
添加监听
springView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
}
@Override
public void onLoadmore() {
}
});
基本使用:配合RecyclerView和默认头部和底部DefaultHeader,DefaultFooter
<?xml version="1.0" encoding="utf-8"?>
<com.liaoinstan.springview.widget.SpringView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/springView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".my.MyDemo1Activity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
</androidx.recyclerview.widget.RecyclerView>
</com.liaoinstan.springview.widget.SpringView>
public class MyDemo1Activity extends AppCompatActivity {
private SpringView mSpringView;
private RecyclerView mRecyclerView;
private List<String> mDatas = new ArrayList<>();
private RvAdapter mRvAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_demo1);
mSpringView = (SpringView) findViewById(R.id.springView);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
//拖拽类型
//OVERLAP 重叠
//FOLLOW 跟随
//DRAG 拖拽
//SCROLL 滚动
mSpringView.setType(SpringView.Type.FOLLOW);
//设置header/footer
mSpringView.setHeader(new DefaultHeader(this));
mSpringView.setFooter(new DefaultFooter(this));
mRvAdapter = new RvAdapter(this, mDatas);
mRecyclerView.setAdapter(mRvAdapter);
loadData();
mSpringView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(() -> {
loadData();
Toast.makeText(MyDemo1Activity.this, "下拉刷新", Toast.LENGTH_SHORT).show();
mSpringView.onFinishFreshAndLoad();
}, 1000);
}
@Override
public void onLoadmore() {
new Handler().postDelayed(() -> {
loadMore();
Toast.makeText(MyDemo1Activity.this, "上拉加载", Toast.LENGTH_SHORT).show();
mSpringView.onFinishFreshAndLoad();
}, 1000);
}
});
}
private void loadData() {
mDatas.clear();
for (int i = 1; i <= 30; i++) {
mDatas.add("赵丽颖" + i);
}
mRvAdapter.notifyDataSetChanged();
}
private void loadMore() {
for (int i = 1; i <= 10; i++) {
mDatas.add("赵丽颖更多" + i);
}
mRvAdapter.notifyDataSetChanged();
}
}
在ScrollView中使用:可以自定义头部和底部布局文件
<?xml version="1.0" encoding="utf-8"?>
<com.liaoinstan.springview.widget.SpringView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/springView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:footer="@layout/default_footer"
app:header="@layout/default_header">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#68b3f3"
android:gravity="center"
android:text="TextView1"
android:textColor="#ffffff" />
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ff0"
android:gravity="center"
android:text="TextView2"
android:textColor="#ffffff" />
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#0f0"
android:gravity="center"
android:text="TextView3"
android:textColor="#ffffff" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</com.liaoinstan.springview.widget.SpringView>
public class MyDemo2Activity extends AppCompatActivity {
private SpringView mSpringView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_demo2);
mSpringView = (SpringView) findViewById(R.id.springView);
mSpringView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(() -> {
Toast.makeText(MyDemo2Activity.this, "下拉刷新", Toast.LENGTH_SHORT).show();
mSpringView.onFinishFreshAndLoad();
}, 2000);
}
@Override
public void onLoadmore() {
new Handler().postDelayed(() -> {
Toast.makeText(MyDemo2Activity.this, "上拉加载", Toast.LENGTH_SHORT).show();
mSpringView.onFinishFreshAndLoad();
}, 2000);
}
});
}
}
在ListView中使用:配合齿轮机械风格头部和底部
<com.liaoinstan.springview.widget.SpringView
android:id="@+id/springview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f9f9f9"
android:divider="@null" />
</com.liaoinstan.springview.widget.SpringView>
RotationHeader:齿轮机械风格
springView.setHeader(new RotationHeader());
springView.setFooter(new RotationFooter());
在RecyclerView中使用:配合阿里旅行风格头部和底部
<com.liaoinstan.springview.widget.SpringView
android:id="@+id/springview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:scrollbars="vertical" />
</com.liaoinstan.springview.widget.SpringView>
AliHeader:阿里旅行风格
springView.setHeader(new AliHeader(this, R.drawable.ali, true)); //参数为:logo图片资源,是否显示文字
springView.setFooter(new AliFooter(this, false));
在WebView中使用:自定义头部布局文件
<com.liaoinstan.springview.widget.SpringView
android:id="@+id/springview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#797a7d"
app:header="@layout/header_web"
app:type="overlap">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.liaoinstan.springview.widget.SpringView>
header_web.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top|center_horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="网页由 github.com 提供"
android:id="@+id/textView2"
android:textColor="#b2b2b2"
android:textSize="12sp"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="wrap_content"
android:textColor="#b2b2b2"
android:text="已启用QQ浏览器X5内核"
android:textSize="12sp"
android:id="@+id/textView3"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
自己编写的头部和底部的布局
<com.liaoinstan.springview.widget.SpringView
android:id="@+id/springView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:footer="@layout/my_footer"
app:header="@layout/my_header">
</androidx.core.widget.NestedScrollView>
my_header
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="70dp">
<ProgressBar
android:id="@+id/default_header_progressbar"
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:id="@+id/default_header_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="下拉刷新"
android:textColor="#777777" />
</LinearLayout>
my_footer
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:gravity="center"
android:layout_height="50dp">
<ProgressBar
android:id="@+id/default_footer_progressbar"
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:id="@+id/default_footer_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#777777"
android:text="加载更多" />
</LinearLayout>
AcfunHeader:AcFun风格
springView.setHeader(new AcFunHeader(this, R.drawable.acfun_header));
springView.setFooter(new AcFunFooter(this, R.drawable.acfun_footer));
Drag Header
简单定制的QQ新年刷红包效果,可以在此基础上自己增加动画特效,这里只是模拟出该效果框架进行演示,故该Header不放在library里面。
具体使用看官方案例。
public class Demo6Activity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
private SpringView springView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo6);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
((RadioGroup) findViewById(R.id.group_header)).setOnCheckedChangeListener(this);
springView = findViewById(R.id.springview);
springView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
//如果当前设置的头部是QQHeader,则不finish
if (springView.getHeader() instanceof QQHeader) return;
new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 1000);
}
@Override
public void onLoadmore() {
new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 1000);
}
});
springView.setHeader(new QQHeader().setMovePara(1.5f)); //设置拖拽系数(值越大,移动越慢)
springView.setFooter(new DefaultFooter(this, R.drawable.progress_small));
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.drag_header:
springView.setHeader(new QQHeader());
break;
case R.id.nomal_header:
springView.setHeader(new DefaultHeader(this));
break;
}
}
}
MeituanHeader,MeituanFooter:美团风格
public class Demo7Activity extends AppCompatActivity {
private SpringView springView;
//下拉过程动画
private int[] pullAnimSrcs = new int[]{R.drawable.mt_pull, R.drawable.mt_pull01, R.drawable.mt_pull02, R.drawable.mt_pull03, R.drawable.mt_pull04, R.drawable.mt_pull05};
//刷新中动画
private int[] refreshAnimSrcs = new int[]{R.drawable.mt_refreshing01, R.drawable.mt_refreshing02, R.drawable.mt_refreshing03, R.drawable.mt_refreshing04, R.drawable.mt_refreshing05, R.drawable.mt_refreshing06};
//加载更多底部动画
private int[] loadingAnimSrcs = new int[]{R.drawable.mt_loading01, R.drawable.mt_loading02};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo7);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
springView = findViewById(R.id.springview);
springView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 2000);
}
@Override
public void onLoadmore() {
new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 2000);
}
});
springView.setHeader(new MeituanHeader(this, pullAnimSrcs, refreshAnimSrcs));
springView.setFooter(new MeituanFooter(this, loadingAnimSrcs));
}
}
SpringView不会和水平滑动有冲突,侧滑删除试试
RecyclerView recyclerView = findViewById(R.id.recycle);
recyclerView.setHasFixedSize(true);
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(mDatas);
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new MyItemTouchCallback(recyclerAdapter));
itemTouchHelper.attachToRecyclerView(recyclerView);
具体使用看官方案例。
TabLayout+ViewPager+Fragment+CoordinatorLayout+CollapsingToolbarLayout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".demo9.Demo9Activity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="centerCrop"
android:src="@drawable/bk_test"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="Demo9Activity" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#5793e6"
app:tabIndicatorHeight="1dp"
app:tabSelectedTextColor="#5793e6"
app:tabTextColor="#665793e6"
tools:background="#33ff0000" />
<!--app:tabTextAppearance="@style/TabLayoutTextStyle"-->
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
具体使用看官方案例。
给header和footer设置为DRAG模式
//给header和footer设置为DRAG模式
springView.setHeader(new MeituanHeader(this, pullAnimSrcs, refreshAnimSrcs).setType(SpringView.Type.DRAG));
springView.setFooter(new MeituanFooter(this, loadingAnimSrcs).setType(SpringView.Type.DRAG));
SpringView 现在支持在内部嵌套布局了(在下拉的头部中嵌套一些布局)
具体使用看官方案例。
实现类似于微信下拉 拉出小程序列表
具体使用看官方案例。
SpringView新增了SCROLL模式,基于这种模式可以实现自动加载等效果,下拉到底部实现自动加载
具体使用看官方案例。
springView.setHeader(new AliHeader(this));
springView.setFooter(new AutoFooter());
DuHeader风格
下拉刷新后弹出:为你更新20条新内容。
<com.liaoinstan.springview.duheader.TopBarFrameLayout
android:id="@+id/top_bar_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.liaoinstan.springview.widget.SpringView
android:id="@+id/springview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ffffff"
android:gravity="center"
android:text="We are in ScrollView"
android:textColor="#cccccc" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ECECF0"
android:gravity="center"
android:text="这是一个仿'毒'APP的效果"
android:textColor="#333333"
android:textSize="12sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ffffff" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ECECF0" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ffffff" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ECECF0" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ffffff" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ECECF0" />
</LinearLayout>
</ScrollView>
</com.liaoinstan.springview.widget.SpringView>
</com.liaoinstan.springview.duheader.TopBarFrameLayout>
topBarFrameLayout = findViewById(R.id.top_bar_frame_layout);
springView = findViewById(R.id.springview);
springView.setListener(new SpringView.OnFreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(() -> {
//0.5秒后再结束header刷新动画(模仿'毒'的延迟,大概0.5秒左右)
springView.onFinishFreshAndLoadDelay(500);
//开始展开topBar顶部提示,并在2.5秒回自动收回
topBarFrameLayout.setTopBarText("为你更新20条新内容");
topBarFrameLayout.showAndHideDelay(2500);
}, 2000);
}
@Override
public void onLoadmore() {
new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 2000);
}
});
springView.setHeader(new DuHeader());
具体使用看官方案例。
如何自定义一个Header或Footer
新建一个MyHeader基础自BaseHeader:
public class MyHeader extends BaseHeader {
private TextView textView;
private int i = 0;
/**
* 获取Header
*
* @param inflater
* @param viewGroup
* @return
*/
@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;
}
/**
* 即将开始拖拽时的回调,可进行初始化操作
*/
@Override
public void onPreDrag(View rootView) {
super.onPreDrag(rootView);
}
/**
* 手指拖拽过程中不断回调,dy为拖拽的距离,可以根据拖动的距离添加拖动过程动画
*
* @param rootView
* @param dy 拖动距离,下拉为+,上拉为-
*/
@Override
public void onDropAnim(View rootView, int dy) {
}
/**
* 手指拖拽过程中每次经过临界点时回调,upORdown是向上经过还是向下经过
*
* @param rootView
* @param upORdown 是上拉还是下拉 true(上),false(下)
*/
@Override
public void onLimitDes(View rootView, boolean upORdown) {
//实现onLimitDes方法,在每次经过临界点时改变TextView的内容:
i++;
textView.setText("松开刷新" + i);
}
/**
* 拉动超过临界点后松开时回调
*/
@Override
public void onStartAnim() {
textView.setText("正在刷新");
}
/**
* 头部已经全部弹回时回调
*/
@Override
public void onFinishAnim() {
textView.setText("下拉刷新");
}
}
mSpringView.setHeader(new MyHeader());
这样就完成了一个简单的自定义Header,Footer同理。
自定义头部Gif图片
public class GifHeader extends BaseHeader {
private GifDrawable mGifDrawable;
private ViewGroup.LayoutParams mLp;
private int mLoadingW = 0, mLoadingH = 0;
private GifImageView mGifImageView;
private Context mContext;
public GifHeader(Context context) {
mContext = context;
}
/**
* 获取Header
*
* @param inflater
* @param viewGroup
* @return
*/
@Override
public View getView(LayoutInflater inflater, ViewGroup viewGroup) {
View view = inflater.inflate(R.layout.gif_header, viewGroup, true);
mGifImageView = view.findViewById(R.id.gif_second);
mGifDrawable = (GifDrawable) mGifImageView.getDrawable();
mLoadingW = dip2px(mContext, 238f);
mLoadingH = dip2px(mContext, 120f);
mLp = mGifImageView.getLayoutParams();
return view;
}
/**
* 即将开始拖拽时的回调,可进行初始化操作
*/
@Override
public void onPreDrag(View rootView) {
super.onPreDrag(rootView);
mGifDrawable.stop();
}
/**
* 手指拖拽过程中不断回调,dy为拖拽的距离,可以根据拖动的距离添加拖动过程动画
*
* @param rootView
* @param dy 拖动距离,下拉为+,上拉为-
*/
@Override
public void onDropAnim(View rootView, int dy) {
if (dy > 238f) {
changeLoadingWH(1);
} else if (dy <= 238f) {
changeLoadingWH(dy / 238f);
}
}
/**
* 手指拖拽过程中每次经过临界点时回调,upORdown是向上经过还是向下经过
* 实现onLimitDes方法,在每次经过临界点时改变TextView的内容:
*
* @param rootView
* @param upORdown 是上拉还是下拉 true(上),false(下)
*/
@Override
public void onLimitDes(View rootView, boolean upORdown) {
}
/**
* 拉动超过临界点后松开时回调
*/
@Override
public void onStartAnim() {
mGifDrawable.start();
}
/**
* 头部已经全部弹回时回调
*/
@Override
public void onFinishAnim() {
mGifDrawable.reset();
mGifDrawable.stop();
}
/**
* 这个方法用于设置当前View的临界高度(limit hight),即拉动到多少会被认定为刷新超作,而没到达该高度则不会执行刷新
* 返回值大于0才有效,如果<=0 则设置为默认header的高度
* 默认返回0
*/
@Override
public int getDragLimitHeight(View rootView) {
return 200;
}
/**
* 这个方法用于设置下拉最大高度(max height),无论怎么拉动都不会超过这个高度
* 返回值大于0才有效,如果<=0 则默认600px
* 默认返回0
*/
@Override
public int getDragMaxHeight(View rootView) {
return 1000;
}
/**
* 这个方法用于设置下拉弹动高度(spring height),即弹动后停止状态的高度
* 返回值大于0才有效,如果<=0 则设置为默认header的高度
* 默认返回0
*/
@Override
public int getDragSpringHeight(View rootView) {
return 450;
}
private void changeLoadingWH(float fraction) {
mLp.width = (int) (mLoadingW * fraction);
mLp.height = (int) (mLoadingH * fraction);
mGifImageView.setLayoutParams(mLp);
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
tools:ignore="MissingDefaultResource">
<pl.droidsonroids.gif.GifImageView
android:id="@+id/gif_second"
android:layout_width="238dp"
android:layout_height="120dp"
android:src="@drawable/refresh_header3"
android:layout_gravity="center" />
</LinearLayout>
自定义Footer
public class MyFooter extends BaseFooter {
private Context context;
private int rotationSrc;
private TextView footerTitle;
private ProgressBar footerProgressbar;
public MyFooter(Context context) {
this(context, R.drawable.progress_small);
}
public MyFooter(Context context, int rotationSrc) {
this.context = context;
this.rotationSrc = rotationSrc;
}
@Override
public View getView(LayoutInflater inflater, ViewGroup viewGroup) {
View view = inflater.inflate(R.layout.default_footer, viewGroup, true);
footerTitle = (TextView) view.findViewById(R.id.default_footer_title);
footerProgressbar = (ProgressBar) view.findViewById(R.id.default_footer_progressbar);
footerProgressbar.setIndeterminateDrawable(ContextCompat.getDrawable(context, rotationSrc));
return view;
}
@Override
public void onPreDrag(View rootView) {
}
@Override
public void onDropAnim(View rootView, int dy) {
}
/**
* 手指拖拽过程中每次经过临界点时回调,upORdown是向上经过还是向下经过
*
* @param rootView
* @param upORdown 是上拉还是下拉 true(上),false(下)
*/
@Override
public void onLimitDes(View rootView, boolean upORdown) {
if (upORdown) {
footerTitle.setText("松开载入更多");
} else {
footerTitle.setText("查看更多");
}
}
@Override
public void onStartAnim() {
footerTitle.setVisibility(View.INVISIBLE);
footerProgressbar.setVisibility(View.VISIBLE);
}
@Override
public void onFinishAnim() {
footerTitle.setText("查看更多");
footerTitle.setVisibility(View.VISIBLE);
footerProgressbar.setVisibility(View.INVISIBLE);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<ProgressBar
android:id="@+id/default_footer_progressbar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:visibility="invisible" />
<TextView
android:id="@+id/default_footer_title"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#777777"
android:text="加载更多" />
</RelativeLayout>
</LinearLayout>
如何自定义最大下拉高度,临界高度,和回弹高度
在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;
}
}