SpringView
android開發(fā)游記:SpringView 下拉刷新的高效解決方案,定制你自己風格的拖拽頁面
SpringView 是一個提供了上下拖拽的功能組件,能夠進行高度自定義,實現(xiàn)各種下拉\上拉動畫效果,demo里實現(xiàn)了:仿阿里旅行、仿美團,仿QQ下拉刷紅包,仿acfun等,完全兼容源生控件如ListView、RecyclerView、ScrollView、WebView等,使用簡單,輕易定制自己風格的拖拽頁面。
SpringView 單獨將頭部/尾部獨立出來,幾乎可以實現(xiàn)任何你想要的效果,只需要繼承BaseHeader(或Footer)實現(xiàn)接口
SpringView 能在運行時動態(tài)地替換頭部/尾部,只需要設置不同的頭尾即可:springView.setHeader(MyHeader());
SpringView 支持多點觸控,可以兩只手連續(xù)拖拽,你可以定制一些非常有趣的效果(例如demo5)
SpringView 提供了2種拖拽方式(重疊和跟隨),可以動態(tài)地切換
SpringView 為不想去自定義頭/尾的懶人提供了7種默認的實現(xiàn)(模仿了阿里,騰訊,美團等多種風格)如下,還會繼續(xù)增加
SpringView 支持和 AppBarLayout 聯(lián)動
如何使用 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,使用代碼動態(tài)添加:
springView.setHeader(new DefaultHeader(this));
springView.setFooter(new DefaultFooter(this));
添加監(jiān)聽
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)); //參數(shù)為: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="網(wǎng)頁由 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內(nèi)核"
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)); //設置拖拽系數(shù)(值越大,移動越慢)
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不會和水平滑動有沖突,側(cè)滑刪除試試
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 現(xiàn)在支持在內(nèi)部嵌套布局了(在下拉的頭部中嵌套一些布局)
具體使用看官方案例。
實現(xiàn)類似于微信下拉 拉出小程序列表
具體使用看官方案例。
SpringView新增了SCROLL模式,基于這種模式可以實現(xiàn)自動加載等效果,下拉到底部實現(xiàn)自動加載
具體使用看官方案例。
springView.setHeader(new AliHeader(this));
springView.setFooter(new AutoFooter());
DuHeader風格
下拉刷新后彈出:為你更新20條新內(nèi)容。

<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秒后再結(jié)束header刷新動畫(模仿'毒'的延遲,大概0.5秒左右)
springView.onFinishFreshAndLoadDelay(500);
//開始展開topBar頂部提示,并在2.5秒回自動收回
topBarFrameLayout.setTopBarText("為你更新20條新內(nèi)容");
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;
}
/**
* 即將開始拖拽時的回調(diào),可進行初始化操作
*/
@Override
public void onPreDrag(View rootView) {
super.onPreDrag(rootView);
}
/**
* 手指拖拽過程中不斷回調(diào),dy為拖拽的距離,可以根據(jù)拖動的距離添加拖動過程動畫
*
* @param rootView
* @param dy 拖動距離,下拉為+,上拉為-
*/
@Override
public void onDropAnim(View rootView, int dy) {
}
/**
* 手指拖拽過程中每次經(jīng)過臨界點時回調(diào),upORdown是向上經(jīng)過還是向下經(jīng)過
*
* @param rootView
* @param upORdown 是上拉還是下拉 true(上),false(下)
*/
@Override
public void onLimitDes(View rootView, boolean upORdown) {
//實現(xiàn)onLimitDes方法,在每次經(jīng)過臨界點時改變TextView的內(nèi)容:
i++;
textView.setText("松開刷新" + i);
}
/**
* 拉動超過臨界點后松開時回調(diào)
*/
@Override
public void onStartAnim() {
textView.setText("正在刷新");
}
/**
* 頭部已經(jīng)全部彈回時回調(diào)
*/
@Override
public void onFinishAnim() {
textView.setText("下拉刷新");
}
}
mSpringView.setHeader(new MyHeader());
這樣就完成了一個簡單的自定義Header,F(xiàn)ooter同理。
自定義頭部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;
}
/**
* 即將開始拖拽時的回調(diào),可進行初始化操作
*/
@Override
public void onPreDrag(View rootView) {
super.onPreDrag(rootView);
mGifDrawable.stop();
}
/**
* 手指拖拽過程中不斷回調(diào),dy為拖拽的距離,可以根據(jù)拖動的距離添加拖動過程動畫
*
* @param rootView
* @param dy 拖動距離,下拉為+,上拉為-
*/
@Override
public void onDropAnim(View rootView, int dy) {
if (dy > 238f) {
changeLoadingWH(1);
} else if (dy <= 238f) {
changeLoadingWH(dy / 238f);
}
}
/**
* 手指拖拽過程中每次經(jīng)過臨界點時回調(diào),upORdown是向上經(jīng)過還是向下經(jīng)過
* 實現(xiàn)onLimitDes方法,在每次經(jīng)過臨界點時改變TextView的內(nèi)容:
*
* @param rootView
* @param upORdown 是上拉還是下拉 true(上),false(下)
*/
@Override
public void onLimitDes(View rootView, boolean upORdown) {
}
/**
* 拉動超過臨界點后松開時回調(diào)
*/
@Override
public void onStartAnim() {
mGifDrawable.start();
}
/**
* 頭部已經(jīng)全部彈回時回調(diào)
*/
@Override
public void onFinishAnim() {
mGifDrawable.reset();
mGifDrawable.stop();
}
/**
* 這個方法用于設置當前View的臨界高度(limit hight),即拉動到多少會被認定為刷新超作,而沒到達該高度則不會執(zhí)行刷新
* 返回值大于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),即彈動后停止狀態(tài)的高度
* 返回值大于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) {
}
/**
* 手指拖拽過程中每次經(jīng)過臨界點時回調(diào),upORdown是向上經(jīng)過還是向下經(jīng)過
*
* @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同理)中默認已經(jīng)實現(xiàn)3個方法,分別返回的是臨界高度(limit hight),下拉最大高度(max height),下拉彈動高度(spring height):
如果有更加復雜的需求,需要更改這些高度的話,就在自己的Header中重寫這些方法,注釋已經(jīng)很清楚了:
public abstract class BaseHeader implements SpringView.DragHander{
/**
* 這個方法用于設置當前View的臨界高度(limit hight),即拉動到多少會被認定為刷新超作,而沒到達該高度則不會執(zhí)行刷新
* 返回值大于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),即彈動后停止狀態(tài)的高度
* 返回值大于0才有效,如果<=0 則設置為默認header的高度
* 默認返回0
*/
@Override
public int getDragSpringHeight(View rootView) {
return 0;
}
}