一、簡(jiǎn)介
SwipeRefreshLayout 是 Google 官方提供的一個(gè)下拉刷新的控件。
注意包的位置:android.support.v4.widget.SwipeRefreshLayout
二、使用
- 用法很簡(jiǎn)單,將需要下拉刷新功能的控件放在 SwipeRefreshLayout 中,注意,SwipeRefreshLayout 只能有一個(gè)子控件。
2.1 xml 布局文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--標(biāo)題欄-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<!--自定義控件-->
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:gravity="center"
android:text="FloatingActionButton"
android:textSize="20dp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<!-- app:layout_behavior="@string/appbar_scrolling_view_behavior" 指定一個(gè)布局行為-->
<!--下拉刷新控件 SwipeRefreshLayout-->
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swiperefreshlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!--RecyclerView-->
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"></android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
<!--FloatingActionButton-->
<android.support.design.widget.FloatingActionButton
android:id="@+id/floating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/floating_icon"
app:fabSize="normal"
app:pressedTranslationZ="10dp"
app:rippleColor="@color/colorAccent"
/>
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
- 可以看到,SwipeRefreshLayout 中包裹了一個(gè) RecyclerView ,也就是說(shuō),RecyclerView 是需要下拉刷新的控件。
2.2 代碼中還有一些設(shè)置
public class MyRecyclerViewActivity extends AppCompatActivity {
@BindView(R.id.floating)
FloatingActionButton floating;
@BindView(R.id.toolbar_title)
TextView toolbarTitle;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.swiperefreshlayout)
SwipeRefreshLayout swiperefreshlayout;
private Snackbar snackbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview_appbarlayout);
ButterKnife.bind(this);
//設(shè)置透明狀態(tài)欄
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
toolbar.setTitle("");
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.setting);
initRecyclerViewData();
initRcyclerView();
initSwipeRefreshLayout();
}
/**
* 初始化下拉刷新控件,SwipeRefreshLayout
*/
private void initSwipeRefreshLayout() {
//設(shè)置刷新進(jìn)度條的顏色變化,最多可以設(shè)置 4 種,加載的顏色是循環(huán)播放的。
swiperefreshlayout.setColorSchemeResources(R.color.colorAccent);
//設(shè)置手指在屏幕上下拉多少會(huì)觸發(fā)下拉刷新
swiperefreshlayout.setDistanceToTriggerSync(300);
//設(shè)置下拉刷新的圓圈背景顏色
swiperefreshlayout.setProgressBackgroundColorSchemeColor(Color.WHITE);
//設(shè)置下拉刷新的圓圈大小
swiperefreshlayout.setSize(SwipeRefreshLayout.DEFAULT);
// 設(shè)置刷新時(shí)候的監(jiān)聽事件
swiperefreshlayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//執(zhí)行刷新之后的操作,一般都是聯(lián)網(wǎng)請(qǐng)求數(shù)據(jù)
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
initData();
myRecyclerAdapter.notifyDataSetChanged();
//停止刷新
swiperefreshlayout.setRefreshing(false);
}
private void initData() {
listData.add("我是刷新時(shí)候添加的數(shù)據(jù)");
listData.add("我是刷新時(shí)候添加的數(shù)據(jù)");
listData.add("我是刷新時(shí)候添加的數(shù)據(jù)");
listData.add("我是刷新時(shí)候添加的數(shù)據(jù)");
}
});
}
}).start();
}
});
2.3 運(yùn)行效果如下:
image
三、添加上拉加載更多
思路: 利用 RecyclerView 的 addOnScrollListener 方法,自己動(dòng)手實(shí)現(xiàn)滑動(dòng)監(jiān)聽,當(dāng)屏幕可見的最后一條條目顯示出來(lái)的時(shí)候,實(shí)現(xiàn)加載更多的邏輯。
3.1 Activity 中使用時(shí)的代碼:
//上拉加載更多
recyclerView.addOnScrollListener(new MyRecyclerViewOnScrollListener(linearLayoutManager) {
@Override
public void loadMoreDate() {
listData.add("我是上拉加載時(shí)候添加的數(shù)據(jù)");
listData.add("我是上拉加載時(shí)候添加的數(shù)據(jù)");
myRecyclerAdapter.notifyDataSetChanged();
}
});
3.2 MyRecyclerViewOnScrollListener 中的代碼:
/**
* RecyclerView 滑動(dòng)監(jiān)聽,目的:實(shí)現(xiàn)上拉加載更過(guò)多
*/
public abstract class MyRecyclerViewOnScrollListener extends RecyclerView.OnScrollListener {
private LinearLayoutManager linearLayoutManager;
//屏幕上可見的 item 數(shù)量
private int visibleItemCount;
//已經(jīng)加載出來(lái)的 item 數(shù)量
private int totalItemCount;
//屏幕上可見的第一個(gè) item
private int firstVisibleItem;
//是否正在上拉加載數(shù)據(jù)中
private boolean isLoadingMore = false;
//記錄之前的數(shù)據(jù)總數(shù)
private int agoneTotle;
public MyRecyclerViewOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.linearLayoutManager = linearLayoutManager;
}
/**
* 滑動(dòng)狀態(tài)改變
*
* @param recyclerView 當(dāng)前滾動(dòng)的 RecyclerView
* @param newState 當(dāng)前滾動(dòng)的狀態(tài),有三個(gè)值
* public static final int SCROLL_STATE_IDLE = 0;靜止沒滾動(dòng)
* public static final int SCROLL_STATE_DRAGGING = 1;用戶正在用手指滾動(dòng)
* public static final int SCROLL_STATE_SETTLING = 2;自動(dòng)滾動(dòng)
*/
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
/**
* 正在滑動(dòng)
*
* @param recyclerView 當(dāng)前滾動(dòng)的 RecyclerView
* @param dx 水平滾動(dòng)距離
* @param dy 垂直滾動(dòng)距離
* dx > 0 時(shí)為手指向左滾動(dòng),列表滾動(dòng)顯示右面的內(nèi)容
* dx < 0 時(shí)為手指向右滾動(dòng),列表滾動(dòng)顯示左面的內(nèi)容
* dy > 0 時(shí)為手指向上滾動(dòng),列表滾動(dòng)顯示下面的內(nèi)容
* dy < 0 時(shí)為手指向下滾動(dòng),列表滾動(dòng)顯示上面的內(nèi)容
*/
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//向下滑動(dòng)
if (dy > 0) {
visibleItemCount = linearLayoutManager.getChildCount();
totalItemCount = linearLayoutManager.getItemCount();
firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition();
}
//如果正在加載中
if(isLoadingMore){
//說(shuō)明加載結(jié)束
if(totalItemCount > agoneTotle){
isLoadingMore = false;
agoneTotle = totalItemCount;
}
}
//如果沒有正在加載中,并且,當(dāng)前屏幕上可見 item 的總數(shù) + 屏幕上可見第一條 item 大于等于 目前加載出來(lái)的數(shù)據(jù)總數(shù)
if (!isLoadingMore && (visibleItemCount + firstVisibleItem) >= totalItemCount) {
isLoadingMore = true;
//加載更多數(shù)據(jù),設(shè)置一個(gè)抽象方法來(lái)實(shí)現(xiàn)具體的加載邏輯
loadMoreDate();
}
}
public abstract void loadMoreDate();
}
- 這種實(shí)現(xiàn)方式?jīng)]有實(shí)現(xiàn)加載時(shí)的加載過(guò)程,用戶感知不到!