全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

android教你打造独一无二的上拉下拉刷新加载框架

其实早在去年七月,群里小伙伴就有让我共享这个。但我当时绝的技术不纯熟。代码有bug什么的。没有写出来。现在感觉整理的差不多了。就写出来让大家看看,有问题一起讨论解决。

说到刷新加载,我们第一个想到啥,对了就是swiperefreshlayout,还有什么SuperSwiperefreshlayout,XRecyclerView等等。反正老多了,我还是之前那句话,不管用什么,我们需要知道他的原理。

打造框架开始

对于刷新加载的实现,你们第一个想到的是什么?是用swiperefresh然后在recyclerview底部加一个不同type?还是用事件拦截呢?那必须是事件拦截啊,虽然现在swiperefreshlayout很火,基本很多app都能看到他。但是遇到那种坑比公司说刷新要用自己公司logo你也没辙。对把。。好了,感觉得罪了好多公司,不管他,我们继续。

我们先看下我们的效果图:

老铁,没毛病。下面我介绍如何实现的。

下拉刷新

首先我们给出如下几个参数,后面要用:

  private NestedScrollingParentHelper helper = null;
  private boolean IsRefresh = true;
  private boolean IsLoad = true;
  //滑动的总距离
  private int totalY = 0;
  private LinearLayout headerLayout = null;
  private MyRecyclerView myRecyclerView = null;
  private LinearLayout footerLayout = null;

既然是刷新,我们的滚动肯定是在父view之前的。所以我们需要在onNestedPreScroll这个方法里面写上我们所需要改动的x,y值。

我们需要用父view去拦截它。

我们需要判断dy的值是否大于0,因为大于0是刷新操作,小于0是加载操作。然后我们需要判断recyclerview是否是纵向的而不是横向的。

public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
    if (IsRefresh) {
      if (dy > 0) {
        if (myRecyclerView.isOrientation(0)) {
          totalY += dy;
          if ((totalY / 2) <= 0) {
            scrollTo(0, totalY / 2);
            consumed[1] = dy;
          } else {
            scrollTo(0, 0);
            consumed[1] = 0;
          }
        }
        return;
      }
    }

上拉加载

上面我也说了onNestedPreScroll这个方法中判断dy<0才是加载操作。所以综上所述,代码变成了这样:

 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
    if (totalY < 0 && myRecyclerView.isOrientation(0) || totalY > 0 && myRecyclerView.isOrientation(1)) {
      isfling = true;
    }
    if (IsRefresh) {
      if (dy > 0) {
        if (myRecyclerView.isOrientation(0)) {
          totalY += dy;
          if ((totalY / 2) <= 0) {
            scrollTo(0, totalY / 2);
            consumed[1] = dy;
          } else {
            scrollTo(0, 0);
            consumed[1] = 0;
          }
        }
        return;
      }
    }
    if (IsLoad) {
      if (dy < 0) {
        if (myRecyclerView.isOrientation(1)) {
          totalY += dy;
          if ((totalY / 2) >= 0) {
            scrollTo(0, totalY / 2);
            consumed[1] = dy;
          } else {
            scrollTo(0, 0);
            consumed[1] = 0;
          }
        }
        return;
      }
    }
  }

最后我们需要在子view滑动结束后,实行如下操作:

 //子view滑动结束调用
  //dyUnconsumed < 0 向下滚
  //dyUnconsumed > 0 向上滚
  public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
    if (dyUnconsumed != 0) {
      totalY += dyUnconsumed;
      scrollTo(0, totalY / 2);
    }
  }

其实最主要的两个方法已经解决了,其他到没什么了,这边,我把nestedscrolling的8个接口的功能和自定义recyclerview放出来。已变大家参考。希望大家都能实现自己的刷新加载。告别swiperefreshlayout。

添加header和footer

这里我们参考listview自带的addheaderview和addfooterview。代码如下:

 public void addHeaderView(View headerView, int headerHeight) {
    this.headerLayout.removeAllViews();
    this.headerLayout.addView(headerView);
    LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, headerHeight);
    layoutParams.topMargin = -headerHeight;
    this.headerLayout.setLayoutParams(layoutParams);
  }

  public void addFooterView(View footerView, int footerHeight) {
    this.footerLayout.removeAllViews();
    this.footerLayout.addView(footerView);
    this.footerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, footerHeight));
  }

几个接口的实现

 public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
    return true;
  }

  public void onNestedScrollAccepted(View child, View target, int axes) {
    helper.onNestedScrollAccepted(child, target, axes);
  }

  //父view拦截子view的滚动
  public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
    if (totalY < 0 && myRecyclerView.isOrientation(0) || totalY > 0 && myRecyclerView.isOrientation(1)) {
      isfling = true;
    }
    if (IsRefresh) {
      if (dy > 0) {
        if (myRecyclerView.isOrientation(0)) {
          totalY += dy;
          if ((totalY / 2) <= 0) {
            scrollTo(0, totalY / 2);
            consumed[1] = dy;
          } else {
            scrollTo(0, 0);
            consumed[1] = 0;
          }
        }
        return;
      }
    }
    if (IsLoad) {
      if (dy < 0) {
        if (myRecyclerView.isOrientation(1)) {
          totalY += dy;
          if ((totalY / 2) >= 0) {
            scrollTo(0, totalY / 2);
            consumed[1] = dy;
          } else {
            scrollTo(0, 0);
            consumed[1] = 0;
          }
        }
        return;
      }
    }
  }

  //子view滑动结束调用
  //dyUnconsumed < 0 向下滚
  //dyUnconsumed > 0 向上滚
  public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
    if (dyUnconsumed != 0) {
      totalY += dyUnconsumed;
      scrollTo(0, totalY / 2);
    }
  }

  public void onStopNestedScroll(View child) {
    helper.onStopNestedScroll(child);
    if (onTouchUpListener != null) {
      isfling = false;
      onTouchUpListener.touchUp();
    }
  }

  public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
    return isfling;
  }

  public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
    return isfling;
  }

  public int getNestedScrollAxes() {
    return helper.getNestedScrollAxes();
  }

自定义recyclerview

既然是自己写的刷新加载框架,总不能还有自定义layout中在放个recyclerview。多麻烦,自定义一个,直接放在里面,然后分别放个header和footer 就没必要每次有页面用到刷新都要写一个布局。3个布局解决整个项目的刷新和加载。话不多说,代码如下:

  private class MyRecyclerView extends RecyclerView {
    private StaggeredGridLayoutManager staggeredGridLayoutManager = null;
    private LinearLayoutManager linearLayoutManager = null;
    private GridLayoutManager gridLayoutManager = null;
    private boolean isScrollLoad = false;
    private boolean isScrollRefresh = false;

    public MyRecyclerView(Context context) {
      super(context);
      setVerticalFadingEdgeEnabled(false);
      setHorizontalFadingEdgeEnabled(false);
      setVerticalScrollBarEnabled(false);
      setHorizontalScrollBarEnabled(false);
      setOverScrollMode(OVER_SCROLL_NEVER);
      setItemAnimator(new DefaultItemAnimator());
    }

    private void setMyLayoutManager(LayoutManager layoutManager) {
      if (layoutManager instanceof StaggeredGridLayoutManager) {
        staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
      } else if (layoutManager instanceof GridLayoutManager) {
        gridLayoutManager = (GridLayoutManager) layoutManager;
      } else if (layoutManager instanceof LinearLayoutManager) {
        linearLayoutManager = (LinearLayoutManager) layoutManager;
      }
      setLayoutManager(layoutManager);
      if (!isVertical()) {
        throw new NullPointerException("vertical!");
      }
    }

    private boolean isOrientation(int orientation) {//orientation,0代表向下,1代表向上
      if (orientation == 0)
        return isCanPullDown();
      else if (orientation == 1)
        return isCanPullUp();
      return false;
    }

    private boolean isCanPullDown() {
      return !canScrollVertically(-1);
    }

    private boolean isCanPullUp() {
      return !canScrollVertically(1);
    }

//    private int scrollLoad() {
//      int lastItem = 0;
//      int itemCount = 0;
//      int spanCount = 1;
//      if (staggeredGridLayoutManager != null) {
//        lastItem = staggeredGridLayoutManager.findLastVisibleItemPositions(null)[0];
//        itemCount = staggeredGridLayoutManager.getItemCount();
//        spanCount = staggeredGridLayoutManager.getSpanCount();
//      } else if (linearLayoutManager != null) {
//        lastItem = linearLayoutManager.findLastVisibleItemPosition();
//        itemCount = linearLayoutManager.getItemCount();
//        spanCount = 1;
//      } else if (gridLayoutManager != null) {
//        lastItem = gridLayoutManager.findLastVisibleItemPosition();
//        itemCount = gridLayoutManager.getItemCount();
//        spanCount = gridLayoutManager.getSpanCount();
//      }
//      return ((itemCount - 1) / spanCount + 1) - (lastItem / spanCount + 1);
//    }

    private boolean isVertical() {
      if (staggeredGridLayoutManager != null)
        return staggeredGridLayoutManager.getOrientation() == StaggeredGridLayoutManager.VERTICAL;
      else if (linearLayoutManager != null)
        return linearLayoutManager.getOrientation() == LinearLayoutManager.VERTICAL;
      else if (gridLayoutManager != null)
        return gridLayoutManager.getOrientation() == GridLayoutManager.VERTICAL;
      return false;
    }

//    public void onScrolled(int dx, int dy) {
//      if (dy > 0 && !isScrollLoad) {
//        if (oLior != null) {
//          onScrollListener.scrollLoad(sc````````
`
``
llLoad());//传递滚动到倒数第几行
//        }
//      }
//    }
  }

这样我们变实现了自己的刷新加载框架,代码我已上传:SWPullRecyclerLayout_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# android  # 刷新框架  # 下拉刷新框架  # 下拉刷新上拉加载框架  # Android通用LoadingView加载框架详解  # android基于dialog实现等待加载框示例  # Android图片加载框架Glide的基本用法介绍  # Android 常见的图片加载框架详细介绍  # Android实现自定义加载框的代码示例  # 详解Android之图片加载框架Fresco基本使用(一)  # 详解Android之图片加载框架Fresco基本使用(二)  # 一起动手编写Android图片加载框架  # 设计简单的Android图片加载框架  # Android自定义加载框效果  # 加载  # 自定义  # 自己的  # 几个  # 第一个  # 都能  # 要用  # 的是  # 我也  # 上滚  # 让我  # 是在  # 好了  # 放在  # 才是  # 就有  # 你也  # 说了  # 但我  # 说到 


相关文章: 网站制作话术技巧,网站推广做的好怎么话术?  IOS倒计时设置UIButton标题title的抖动问题  c# 在高并发下使用反射发射(Reflection.Emit)的性能  网站制作公司,橙子建站是合法的吗?  个人摄影网站制作流程,摄影爱好者都去什么网站?  建站主机选虚拟主机还是云服务器更好?  如何撰写建站申请书?关键要点有哪些?  建站主机SSH密钥生成步骤及常见问题解答?  如何通过二级域名建站提升品牌影响力?  建站之星导航菜单设置与功能模块配置全攻略  安云自助建站系统如何快速提升SEO排名?  如何选择高效可靠的多用户建站源码资源?  番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?  在线制作视频网站免费,都有哪些好的动漫网站?  php8.4新语法match怎么用_php8.4match表达式替代switch【方法】  建站之星IIS配置教程:代码生成技巧与站点搭建指南  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  如何用VPS主机快速搭建个人网站?  合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?  移民网站制作流程,怎么看加拿大移民官网?  制作网站外包平台,自动化接单网站有哪些?  如何有效防御Web建站篡改攻击?  开源网站制作软件,开源网站什么意思?  如何快速搭建FTP站点实现文件共享?  长沙做网站要多少钱,长沙国安网络怎么样?  如何快速使用云服务器搭建个人网站?  建站主机选哪家性价比最高?  内网网站制作软件,内网的网站如何发布到外网?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  深圳 网站制作,深圳招聘网站哪个比较好一点啊?  建站中国官网:模板定制+SEO优化+建站流程一站式指南  如何在Windows虚拟主机上快速搭建网站?  小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建  建站之星免费模板:自助建站系统与智能响应式一键生成  北京专业网站制作设计师招聘,北京白云观官方网站?  测试制作网站有哪些,测试性取向的权威测试或者网站?  网站好制作吗知乎,网站开发好学吗?有什么技巧?  C++中引用和指针有什么区别?(代码说明)  建站主机服务器选购指南:轻量应用与VPS配置解析  网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  建站之星如何快速解决建站难题?  免费公司网站制作软件,如何申请免费主页空间做自己的网站?  北京网站制作公司哪家好一点,北京租房网站有哪些?  深圳企业网站制作设计,在深圳如何网上全流程注册公司?  上海网站制作网页,上海本地的生活网站有哪些?最好包括生活的各个方面的?  如何快速搭建高效可靠的建站解决方案?  c# await 一个已经完成的Task会发生什么  微课制作网站有哪些,微课网怎么进?  如何选择可靠的免备案建站服务器? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。