SwipeRefreshLayout与RecyclerView的巧夺天工(一)

简介: SwipeRefreshLayout与RecyclerView的巧夺天工(一)

平常开发我们需要使用ListView下拉刷新或者其上滑加载的时候,不是自己写就是用别人写好了,但是编程中有一点是不变的,就是一般封装好的东西,其扩展性极低,比如你使用xutils,imageloader等开源框架的时候,它允许你扩展吗?答案当然是否,那我想要实现自己非常酷酷的ListView时候,只有自己动手实现。不过,谷歌在2015在v4开发包加入 豪华套餐SwipeRefreshLayout供你享用。


1.SwipeRefreshLayout使用注意说明


㈠SwipeRefreshLayout默认只能包含一个滑动控件,比如本文使用的RecyclerView。


㈡一般使用ListView组件都有一个需求,那么就是没有网络的情况下,将显示其他控件提示用户加载失败或者需要联网。那么,SwipeRefreshLayout可以包含有且仅有一个布局,布局里面可以添加你需要的控件。


㈢如果你按㈡这样做,那么SwipeRefreshLayout默认只会监听一个滑动控件,当你有多个控件的时候会使其找不到监听的滑动控件。这样SwipeRefreshLayout功能就不复存在了。


㈣那么今天我们将实现的下拉刷新和上滑加载该怎么办呢?答案就是重写SwipeRefreshLayout。


2.重写SwipeRefreshLayout


当我们重写SwipeRefreshLayout,需要使用到如下一个方法:


㈠canChildScrollUp


我们来看看其文档说明:

public boolean canChildScrollUp ()
Returns
Whether it is possible for the child view of this layout to scroll up. Override this if the child view is a custom view.


如果子视图为自定义视图那么必须重写该方法。同理,当你的子视图用布局包裹的时候,其就是你自定义的,除非你的子视图只有ListView,当有多个控件时候,其默认找不到ListView监听其滑动事件,必须重写该方法。


㈡重写SwipeRefreshLayout

既然找不到该子视图,那么就必须传入子视图的控件,以监听其滑动状态,也就是自定义一个属性:

<declare-styleable name="LYJSwipeLayoutAttrs">
    <attr name="scrollableChildId" format="reference" />
</declare-styleable>


下面源码是怎么写的canChildScrollUp:

public boolean canChildScrollUp() {
    if (android.os.Build.VERSION.SDK_INT < 14) {
        if (mTarget instanceof AbsListView) {
            final AbsListView absListView = (AbsListView) mTarget;
            return absListView.getChildCount() > 0
                    && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                            .getTop() < absListView.getPaddingTop());
        } else {
            return ViewCompat.canScrollVertically(mTarget, -1) || mTarget.getScrollY() > 0;
        }
    } else {
        return ViewCompat.canScrollVertically(mTarget, -1);
    }
}

下面我们来依葫芦画瓢重写SwipeRefreshLayout:

public class LYJSwipeRefreshLayout extends SwipeRefreshLayout {
    private static final String TAG = LYJSwipeRefreshLayout.class.getCanonicalName();
    private int mScrollableChildId;//控件ID
    private View mScrollableChild;//子控件
    public LYJSwipeRefreshLayout(Context context) {
        this(context, null);
    }
    public LYJSwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //获取监听子控件的ID
        TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.LYJSwipeLayoutAttrs);
        mScrollableChildId = a.getResourceId(R.styleable.LYJSwipeLayoutAttrs_scrollableChildId, 0);
        mScrollableChild = findViewById(mScrollableChildId);
        a.recycle();
    }
    @Override
    public boolean canChildScrollUp() {
        //判断有没有传入子控件
        ensureScrollableChild();
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (mScrollableChild instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) mScrollableChild;
                return absListView.getChildCount() > 0
                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                        .getTop() < absListView.getPaddingTop());
            } else {
                return mScrollableChild.getScrollY() > 0;
            }
        } else {
            return ViewCompat.canScrollVertically(mScrollableChild, -1);
        }
    }
    private void ensureScrollableChild() {
        if (mScrollableChild == null) {
            mScrollableChild = findViewById(mScrollableChildId);
        }
    }
}


布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <android.support.v7.widget.Toolbar
        android:id="@+id/activity_main_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/activity_main_tablayout_bg">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_gravity="center"
            android:text="@string/app_name"
            android:textColor="@android:color/black"
            android:textSize="20sp"
            android:textStyle="bold" />
    </android.support.v7.widget.Toolbar>
    <com.example.liyuanjing.welltestdemo.LYJSwipeRefreshLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/activity_main_swipe"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:scrollableChildId="@+id/activity_main_recyclerview"
        android:background="@android:color/transparent">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <android.support.v7.widget.RecyclerView
                android:id="@+id/activity_main_recyclerview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:cacheColorHint="@null"
                android:scrollbars="vertical" />
            <LinearLayout
                android:id="@+id/activity_main_linearlayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"/>
        </FrameLayout>
    </com.example.liyuanjing.welltestdemo.LYJSwipeRefreshLayout>
</LinearLayout>


红色标记的为传入子控件ID的属性。这样SwipeRefreshLayout就可以监听recyclerview了。

相关文章
|
搜索推荐 Java 开发工具
RecyclerView的那点事儿
RecyclerView的那点事儿
81 0
|
前端开发 Android开发
RecyclerView实现吸底效果—ItemDecoration
RecyclerView实现吸底效果—ItemDecoration
SwipeRefreshLayout与RecyclerView的巧夺天工(二)
SwipeRefreshLayout与RecyclerView的巧夺天工(二)
70 0
SwipeRefreshLayout与RecyclerView的巧夺天工(二)
|
开发工具 Android开发
RecyclerView与CardView的使用(一)
RecyclerView与CardView的使用(一)
143 0
RecyclerView与CardView的使用(一)
RecyclerView与CardView的使用(二)
RecyclerView与CardView的使用(二)
114 0
RecyclerView与CardView的使用(二)
|
存储 缓存 Java
RecyclerView问题汇总
目录介绍 25.0.0.0 请说一下RecyclerView?adapter的作用是什么,几个方法是做什么用的?如何理解adapter订阅者模式? 25.0.0.1 ViewHolder的作用是什么?如何理解ViewHolder的复用?什么时候停止调用onCreateViewHolder? 25.
3036 0