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了。

相关文章
|
SQL 关系型数据库 MySQL
mysql 常见面试题
mysql 常见面试题
196 0
|
关系型数据库 数据库
本地MariaDB数据库外网访问
外网访问本地MariaDB数据库 本地安装了MariaDB数据库,只能在局域网内访问,怎样从公网也能访问内网MariaDB数据库? 本文将介绍具体的实现步骤。 1. 准备工作 1.1 安装并启动MariaDB数据库 默认安装的MariaDB数据库端口是3306。
4541 0
|
安全 API 数据安全/隐私保护
微服务的安全性考虑
【8月更文第29天】随着微服务架构的流行,确保这些服务的安全性成为了系统设计中的一个关键因素。本文将探讨微服务环境下如何确保数据安全、API 安全以及网络通信的安全,并提供相应的代码示例。
244 0
|
算法 异构计算
推测解码:在不降低准确性的情况下将LLM推理速度提高2 - 3倍
在本篇文章我们将详细讨论推测解码,这是一种可以将LLM推理速度提高约2 - 3倍而不降低任何准确性的方法。我们还将会介绍推测解码代码实现,并看看它与原始transformer 实现相比到底能快多少。
520 10
|
数据采集 搜索推荐 安全
如何做好上海SEO网站推广?
答案是:做足够多的GPB外链+足够多的优质内容。 了解上海的市场环境 上海,作为国内的经济、文化、金融和国际交往中心,具有独特的市场环境和消费者行为。 为了做好SEO推广,首先需要深入了解上海的市场特点。 消费者习惯 上海的消费者在搜索习惯、信息获取方式和购物习惯上都存在一些特点,这些都需要在SEO策略中得到体现。 行业竞争 上海的竞争尤为激烈,了解竞争对手的推广策略和关键词布局是成功的关键。
215 0
如何做好上海SEO网站推广?
|
存储 运维 Kubernetes
构建高效自动化运维体系:Ansible与Kubernetes的协同实践
【5月更文挑战第2天】随着云计算和微服务架构的兴起,自动化运维成为保障系统稳定性与效率的关键。本文将深入探讨如何利用Ansible作为配置管理工具,结合Kubernetes容器编排能力,共同打造一个高效、可靠的自动化运维体系。通过剖析二者的整合策略及具体操作步骤,为读者提供一套提升运维效率、降低人为错误的实用解决方案。
|
云安全 监控 安全
网络智能服务标准版
“网络智能服务标准版”是阿里云提供的一种云端网络安全服务,可以帮助用户对网络流量进行实时监控、分析和防御。该服务可以自动识别和拦截恶意流量,保护用户的网络安全。
972 2
|
Oracle 关系型数据库 数据库
PLSQL连接本地oracle或远程oracle数据库,实现随意切换
PLSQL连接本地oracle或远程oracle数据库,实现随意切换
|
Windows
EasyRecovery for Mac15免费版数据恢复软件
作为办公的必需品,mac的普及率虽然比不上其他品牌的windows操作系统,但是使用人群也一致居高不下,因此,mac数据丢失的问题也时常发生。当数据丢失以后,如何找回数据成了一大难题。那么,mac数据丢失怎么恢复?
261 0
|
网络协议 安全 Windows
图解网络:TCP三次握手背后的原理,为啥两次握手不可以?
TCP是 Internet 协议套件的主要协议之一,它位于应用层和网络层之间,用于提供可靠的连接服务,是一种面向连接的通信协议,有助于通过网络在不同设备之间交换消息。
266 0
图解网络:TCP三次握手背后的原理,为啥两次握手不可以?