时间:2021-05-20
其实早在去年七月,群里小伙伴就有让我共享这个。但我当时绝的技术不纯熟。代码有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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
不管是人或物,似乎都在追求自己的独特性,但如何真正打造自身的独一无二却是一门技术活,打造独一无二的网站更是无数网建人的梦想。拥有十年的网建经验,专业更敬业,教你
(图片为【山哥】实操店铺后台数据,独一无二)(图片为【山哥】实操店铺后台数据,独一无二)(图片为【山哥】实操店铺后台数据,独一无二)(图片为【山哥】实操店铺后台
本文实例为大家分享了Android实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下先分享下源码:Android实现下拉刷新和上拉加载更多实现思路:
本文实例为大家分享了Android刷新加载框架的具体代码,供大家参考,具体内容如下1.定义一个接口控制下拉和上拉publicinterfacePullable{
独一无二网站建设公司-小编认为每个网站设计项目对客户来说都是独一无二,对我们来说更是如此,既然都要花钱了,为什么还要用模板,每个网站看起来都一模一样,没有独特性