android 简单封装上拉刷新,下拉加载功能_封装刷新加载功能 android-程序员宅基地

技术标签: android 下拉加载  功能  android 上拉刷新  android 上拉刷新下拉加载  

从开源中国控件里而来,并自己改进一些功能

BaseRecyclerRefreshLayout:

主要用于控制全局的手势是否上拉刷新,正常滑动,下拉加载三种情况.手势控制源头

public class BaseRecyclerRefreshLayout extends SwipeRefreshLayout implements SwipeRefreshLayout.OnRefreshListener {
    private RecyclerView mRecycleView;

    private int mTouchSlop;

    private SuperRefreshLayoutListener listener;

    private boolean mIsOnLoading = false;

    private boolean mCanLoadMore = true;

    private boolean mHasMore = true;

    private int mYDown;

    private int mLastY;

    public BaseRecyclerRefreshLayout(Context context) {
        this(context, null);
    }

    public BaseRecyclerRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        setOnRefreshListener(this);
        setColorSchemeResources(R.color.colorAccent);   //TODO 设置转圈颜色跟随控件选中颜色
    }


    @Override
    public void onRefresh() {
        if (listener != null && !mIsOnLoading) {
            listener.onRefreshing();
        } else
            setRefreshing(false);
    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        // 初始化ListView对象
        if (mRecycleView == null) {
            getRecycleView();
        }
    }

    /**
     * 获取RecyclerView
     */
    private void getRecycleView() {
        if (getChildCount() > 0) {
            View childView = getChildAt(0);
            if (!(childView instanceof RecyclerView)) {
                childView = findViewById(R.id.recyclerView);    //TODO 只要布局里有id=recyclerView就可以了
            }
            if (childView != null && childView instanceof RecyclerView) {
                mRecycleView = (RecyclerView) childView;
                mRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

                    }

                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                        if (canLoad() && mCanLoadMore) {    //向下拉,最后一个可见条目,有更多数据标记,不是正在加载,能加载更多
                            loadData();
                        }
                    }
                });
            }
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mYDown = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                mLastY = (int) event.getRawY();
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(event);
    }

    /**
     * 是否可以加载更多, 条件是到了最底部
     *
     * @return isCanLoad
     */
    private boolean canLoad() {
        return isScrollBottom() && !mIsOnLoading && isPullUp() && mHasMore;
    }

    /**
     * 如果到了最底部,而且是上拉操作.那么执行onLoad方法
     */
    private void loadData() {
        if (listener != null) {
            setOnLoading(true);
            listener.onLoadMore();
        }
    }

    /**
     * 是否是上拉操作
     *
     * @return isPullUp
     */
    private boolean isPullUp() {
        return (mYDown - mLastY) >= mTouchSlop;
    }

    /**
     * 设置正在加载
     *
     * @param loading 设置正在加载
     */
    public void setOnLoading(boolean loading) {
        mIsOnLoading = loading;
        if (!mIsOnLoading) {
            mYDown = 0;
            mLastY = 0;
        }
    }

    /**
     * 判断是否到了最底部
     */
    private boolean isScrollBottom() {
        return (mRecycleView != null && mRecycleView.getAdapter() != null)
                && getLastVisiblePosition() == (mRecycleView.getAdapter().getItemCount() - 1);
    }

    /**
     * 加载结束记得调用
     */
    public void onComplete() {
        setOnLoading(false);
        setRefreshing(false);
        mHasMore = true;
    }

    /**
     * 是否可加载更多
     *
     * @param mCanLoadMore 是否可加载更多
     */
    public void setCanLoadMore(boolean mCanLoadMore) {
        this.mCanLoadMore = mCanLoadMore;
    }

    /**
     * 获取RecyclerView可见的最后一项
     *
     * @return 可见的最后一项position
     */
    public int getLastVisiblePosition() {
        int position;
        if (mRecycleView.getLayoutManager() instanceof LinearLayoutManager) {
            position = ((LinearLayoutManager) mRecycleView.getLayoutManager()).findLastVisibleItemPosition();
        } else if (mRecycleView.getLayoutManager() instanceof GridLayoutManager) {
            position = ((GridLayoutManager) mRecycleView.getLayoutManager()).findLastVisibleItemPosition();
        } else if (mRecycleView.getLayoutManager() instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) mRecycleView.getLayoutManager();
            int[] lastPositions = layoutManager.findLastVisibleItemPositions(new int[layoutManager.getSpanCount()]);
            position = getMaxPosition(lastPositions);
        } else {
            position = mRecycleView.getLayoutManager().getItemCount() - 1;
        }
        return position;
    }

    /**
     * 获得最大的位置
     *
     * @param positions 获得最大的位置
     * @return 获得最大的位置
     */
    private int getMaxPosition(int[] positions) {
        int maxPosition = Integer.MIN_VALUE;
        for (int position : positions) {
            maxPosition = Math.max(maxPosition, position);
        }
        return maxPosition;
    }

    /**
     * 添加加载和刷新
     *
     * @param listener add the listener for SuperRefreshLayout
     */
    public void setSuperRefreshLayoutListener(SuperRefreshLayoutListener listener) {
        this.listener = listener;
    }

    public interface SuperRefreshLayoutListener {
        void onRefreshing();

        void onLoadMore();
    }
}

BaseFragment:

主要提供别的Fragment继承的,封装一些常用的方法

/**
 * Fragment基础类
 */

@SuppressWarnings("WeakerAccess")   //弱引用
public abstract class BaseFragment extends Fragment {
    protected Context mContext;
    protected View mRoot;
    protected Bundle mBundle;
    protected LayoutInflater mInflater;
    private Fragment mFragment;
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mContext = null;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBundle = getArguments();
        initBundle(mBundle);    //拿到传过来的数据参数
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (mRoot != null) {        //复用自己本身的View,如果没有就进行重新加载
            ViewGroup parent = (ViewGroup) mRoot.getParent();
            if (parent != null)
                parent.removeView(mRoot);
        } else {
            mRoot = inflater.inflate(getLayoutId(), container, false);
            mInflater = inflater;
            // Do something
            onBindViewBefore(mRoot);
            // Bind view
            // Get savedInstanceState
            if (savedInstanceState != null)
                onRestartInstance(savedInstanceState);
            // Init  --> 初始化
            initWidget(mRoot);
            initData();
        }
        return mRoot;
    }

    //控制Fragment显示和隐藏
    public void addFragment(int frameLayoutId, Fragment fragment) {  //应该对Fragment进行管理,使用一个实例Fragment

        if (fragment != null) {
            FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
            //已经有过该fragment(没有带参数的),
            if (fragment.getArguments() == null && getChildFragmentManager().findFragmentByTag(fragment.getClass().getName()) != null) {
                if (mFragment != null && mFragment.getClass().getName().equals(fragment.getClass().getName())) { //添加的是同一个Fragment(不同对象) 不改变
                    return; // hide和add 为同一个Fragment不同对象
                }
                if (mFragment != null) {
                    Fragment fragmentByTag = getChildFragmentManager().findFragmentByTag(fragment.getClass().getName());
                    fragment = fragmentByTag;   //必须进行赋值,不然以后隐藏 mFragment 会进行出错
                    transaction.hide(mFragment).show(fragmentByTag);
                } else {
                    transaction.add(frameLayoutId, fragment, fragment.getClass().getName());
                }
            } else {    //有参数的fragment不管有没有添加过相同的显示新的fragment
                if (mFragment != null) {
                    if (mFragment.getClass().getName().equals(fragment.getClass().getName())) { //添加的为同一个fragment
                        transaction.remove(mFragment);
                        transaction.add(frameLayoutId,fragment,fragment.getClass().g
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jinrumorijuesha/article/details/88122748

智能推荐

Android Studio一个项目引入另一个项目作为依赖Libary(富文本编辑器版本)_android 如果引用一个项目作为lib-程序员宅基地

文章浏览阅读975次。文章目录一、源码,详见地址二、实践篇1、导入依赖项目​2、配置添加依赖项目3、把依赖项目设置为兼容的library(错误解决)声明:本教程不收取任何费用,欢迎转载,尊重作者劳动成果,不得用于商业用途,侵权必究!!!大概是在去年12月份写了一篇这样的文章,最近参照来看发现看的有些费劲,因为当时用的Markdown编辑器所以编辑和排版都相对比较麻烦不好观看,所以决定重新写一..._android 如果引用一个项目作为lib

Quartz_quartz毕设参考文献-程序员宅基地

文章浏览阅读97次。这里是修真院后端小课堂,每篇分享文从八个方面深度解析后端知识/技能,本篇分享的是:【Quartz】【修真院Java小课堂】任务调度-Quartz开场语:大家好,我是IT修真院北京分院第32期的学员廖友,一枚正直纯洁善良的Java程序员,今天给大家分享一下,修真院官网Java任务十中的知识点——任务调度-Quartz一、背景介绍:1、任务调度概念任务调度是指基于给定时间点,给定时间间..._quartz毕设参考文献

linux系统下无法用SecureCRT及putty工具远程登录系统方法-程序员宅基地

文章浏览阅读191次。一般情况下,我们安装好了linux系统,都希望通过工具能够进行远程管理,这样可以方便许多,但是有时候却无法通过这些工具连接,主要是由于我们没有安装远程的服务,如ssh及telnet这2个服务!命令方式安装:sudo apt-get install ssh 安装telnet方法:sudo apt-get install telnet Telnet..._linux不能通过工具访问远程

The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You mu-程序员宅基地

文章浏览阅读174次。在做springboot连接数据库时:方案1:在项目代码-数据库连接URL后,加上 (注意大小写必须一致)?serverTimezone=UTC方案2:在mysql中设置时区,默认为SYSTEM set global time_zone='+8:00'错误原因:使用了Mysql Connector/J 6.x以上的版本,然set global time_zone='+8:0...

解决经过zuul网关,文件上传失败问题_zuul网关 file not allowed to upload!-程序员宅基地

文章浏览阅读4.1k次。在Spring Cloud Zuul中,Zuul本身有几个核心过滤器源码如下:其中 ServletDetectionFilter优先级最高 为-3 ,所以最先执行,这个核心过滤器只是做了一个判断当前请求是通过Spring的DispatcherServlet处理运行,还是通过ZuulServlet来处理运行,并把结果放回上下文中。一般般情况下,发送到API网关的外部请求都会被Spring..._zuul网关 file not allowed to upload!

使用Python 进行串口通信过程记录——PySerial安装_phthon 脱机安装串口模块-程序员宅基地

文章浏览阅读3.6k次。该文章的前提是已安装Python(楼主安装版本为64bit的3.7版本),使用PySerial模块,该模块安装前可先安装pip(推荐安装,还可以用于安装其他模块,使用方便)一、安装PIP1、下载安装包,地址为:https://pypi.org/project/pip/#files2、下载完成后将其解压到python目录下:随后,cmd进入该目录下,并进入到pip-19.0..._phthon 脱机安装串口模块

随便推点

在python moviepy中编辑后的视频没有声音的解决方案_moviepy 音频不加载-程序员宅基地

文章浏览阅读3.2k次。据说是mac下才会发生,其实不是的,和播放器的音频解码方式有关,大家在调用write_videofile函数时加上参数audio_codec="aac",改变下声道编码即可_moviepy 音频不加载

无法打开文件MSVCRTD.lib VS2017_无法打开文件“msvcrtd.lib”-程序员宅基地

文章浏览阅读1.9k次。_无法打开文件“msvcrtd.lib”

完善动态so加载库-程序员宅基地

文章浏览阅读96次。以上代码包括实验代码,都能在这里找到SillyBoy作者:Pika链接:https://juejin.cn/post/7227029203656867899来源:稀土掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。_动态so

OPENSSL之计算SHA1散列值_基于openssl实现sha1算法哈希运算-程序员宅基地

文章浏览阅读1k次。今天遇到了sha的相关函数的应用,随手收集了点有用的资料,以后在看。。。。。。。HA1散列函数是很常用的散列函数,它产生160bit(20字节)长度的散列值。今天,我就来介绍利用OpenSSL现成的API来计算数据的SHA1散列值。先来看OpenSSL的相关API声明: #include unsigned char *SHA_基于openssl实现sha1算法哈希运算

【Unity 24】Unity中的向量点乘和叉乘的应用_3d游戏中向量叉乘-程序员宅基地

文章浏览阅读4.6k次,点赞10次,收藏32次。PS:本系列笔记将会记录我此次在北京学习Unity开发的总体过程,方便后期写总结,笔记为日更。笔记内容均为 自己理解,不保证每个都对点乘求角度,叉乘求方向比如敌人再附近,点乘可以求出玩家面朝方向和敌人方向的夹角,叉乘可以得出左转还是右转更好的转向敌人Part 1 点乘:数学上的 点乘为 a * b = |a| * |b| * cos(Θ) Unity中的点乘也是如此 点乘结果为 ..._3d游戏中向量叉乘

poj 3468 A Simple Problem with Integers(线段树)(第二部分 成段更新,区间求和)-程序员宅基地

文章浏览阅读262次。题目链接:http://poj.org/problem?id=3468题目大意:给出n个数的数值Q是对区间a,b的求和C是对区间a,b内的所有数都加上c思路:成段更新,需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候#include#include#include#include#inc

推荐文章

热门文章

相关标签