实现方式是不改变RecyclerView本身,定义了一个父控件装载,查看更多和架子更多的view也同样作为该父控件的子控件。有简单的阻尼回弹效果。
实现代码:


public class PulToLeftViewGroupl extends LinearLayout implements ViewTreeObserver.OnGlobalLayoutListener {OnPullToLeftListener mOnPullToLeftListener;public void setOnPullToLeftListener(OnPullToLeftListener leftListener){this.mOnPullToLeftListener = leftListener;}public interface OnPullToLeftListener{/*** 松开手指去更新-可能需要动画在此函数实现*/void onReleaseFingerToUpload();/*** 开始拉出查看更多-可能需要动画在此函数实现*/void onStartToUpload();}/*** 动画时间*/private static final long ANIM_TIME = 200;//recyclerviewprivate View childView;// 用于记录正常的布局位置private Rect originalRect = new Rect();//滚动时,移动的view和位置private List<View> mMoveViews = new ArrayList<>();private List<Rect> mMoveRects = new ArrayList<>();// 在手指滑动的过程中记录是否移动了布局private boolean isMoved = false;// 如果按下时不能上拉和下拉, 会在手指移动时更新为当前手指的Y值private float startY;//阻尼private static final float OFFSET_RADIO = 0.6f;private boolean isRecyclerReuslt = false;public PulToLeftViewGroupl(Context context) {super(context);}public PulToLeftViewGroupl(Context context, AttributeSet attrs) {super(context, attrs);}public PulToLeftViewGroupl(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}/*** 完成更新调用*/public void completeToUpload(){postDelayed(new Runnable() {@Overridepublic void run() {recoverLayout();}}, 1500);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);originalRect.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());for (int i = 0; i < mMoveViews.size(); i++) {final View v = mMoveViews.get(i);v.addOnLayoutChangeListener(new OnLayoutChangeListener() {@Overridepublic void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {Rect rect = new Rect();rect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());mMoveRects.add(rect);v.removeOnLayoutChangeListener(this);}});}}/*** 加载布局后初始化,这个方法会在加载完布局后调用*/@Overrideprotected void onFinishInflate() {if (getChildCount() > 0) {for (int i = 0; i < getChildCount(); i++) {if (getChildAt(i) instanceof RecyclerView) {if (childView == null) {childView = getChildAt(i);} else {throw new RuntimeException("只能存在一个RecyclerView");}}}}if (childView == null) {throw new RuntimeException("子容器中必须有一个RecyclerView");}//布局重绘监听,比如华为屏幕键盘可以弹出和隐藏,改变布局,加监听就可以虽键盘弹出关闭的变化而变化getViewTreeObserver().addOnGlobalLayoutListener(this);super.onFinishInflate();}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)@Overridepublic void onGlobalLayout() {requestLayout();getViewTreeObserver().removeOnGlobalLayoutListener(this);}/*** 跟随弹性移动的view* @param view*/public void setMoveViews(View view) {this.mMoveViews.add(view);requestLayout();}/*** 位置还原*/private void recoverLayout() {if (!isMoved) {return;//如果没有移动布局,则跳过执行}for (int i = 0; i < mMoveViews.size(); i++) {if (i < mMoveRects.size()) {if (mMoveRects.get(i) != null) {final int indexAt = i;TranslateAnimation anims = new TranslateAnimation(mMoveViews.get(i).getRight(), mMoveRects.get(i).right, 0, 0);anims.setDuration(ANIM_TIME);mMoveViews.get(i).startAnimation(anims);mMoveViews.get(indexAt).layout(mMoveRects.get(indexAt).left,mMoveRects.get(indexAt).top,mMoveRects.get(indexAt).right,mMoveRects.get(indexAt).bottom);}}}TranslateAnimation anim = new TranslateAnimation(childView.getRight() - originalRect.right, 0, 0,0);anim.setDuration(ANIM_TIME);childView.startAnimation(anim);childView.layout(originalRect.left, originalRect.top, originalRect.right, originalRect.bottom);isMoved = false;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return false;  //不拦截  直接传递给子的view}/*** 判断是否可以上拉* @return*/private boolean isCanPullUp() {final RecyclerView.Adapter adapter = ((RecyclerView) childView).getAdapter();if (null == adapter) {return true;}final int lastItemPosition = adapter.getItemCount() - 1;final int lastVisiblePosition = ((LinearLayoutManager) ((RecyclerView) childView).getLayoutManager()).findLastVisibleItemPosition();if (lastVisiblePosition >= lastItemPosition) {final int childIndex = lastVisiblePosition - ((LinearLayoutManager) ((RecyclerView) childView).getLayoutManager()).findFirstVisibleItemPosition();final int childCount = ((RecyclerView) childView).getChildCount();final int index = Math.max(childIndex, childCount - 1);final View lastVisibleChild = ((RecyclerView) childView).getChildAt(index);if (lastVisibleChild != null) {return lastVisibleChild.getRight() <= childView.getRight() - childView.getLeft();}}return false;}/*** 事件分发*/@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {if (childView == null) {return super.dispatchTouchEvent(ev);}boolean isTouchOutOfScrollView = ev.getX() >= originalRect.right || ev.getX() <= originalRect.left; //如果当前view的Y上的位置if (isTouchOutOfScrollView) {//如果不在view的范围内if (isMoved) {      //当前容器已经被移动recoverLayout();}return true;}int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN://记录按下时的XstartY = ev.getX();case MotionEvent.ACTION_MOVE:float nowX = ev.getX();int scrollX = (int) (nowX - startY);if ((isCanPullUp() && scrollX < 0)) {int offset = (int) (scrollX * OFFSET_RADIO);childView.layout(originalRect.left + offset, originalRect.top, originalRect.right + offset, originalRect.bottom);for (int i = 0; i < mMoveViews.size(); i++) {if (i < mMoveRects.size()) {if (mMoveViews.get(i) != null && mMoveRects.get(i) != null) {mMoveViews.get(i).layout(mMoveRects.get(i).left + offset,mMoveRects.get(i).top,mMoveRects.get(i).right + offset,mMoveRects.get(i).bottom);}}}isMoved = true;isRecyclerReuslt = false;if (mOnPullToLeftListener!=null){mOnPullToLeftListener.onStartToUpload();}return true;} else {startY = ev.getX();isMoved = false;isRecyclerReuslt = true;recoverLayout();return super.dispatchTouchEvent(ev);}case MotionEvent.ACTION_UP:if (isMoved && mOnPullToLeftListener!=null) {//recoverLayout();mOnPullToLeftListener.onReleaseFingerToUpload();}if (isRecyclerReuslt) {return super.dispatchTouchEvent(ev);} else {return true;}default:return true;}}}

需要注意的地方有RecyclerView的Manager只处理了LinearLayoutManager.如果需要其他类型的Manager,请自行改写isCanPullUp()函数。

eg使用例子:
布局文件xml中代码:

 <pull_to_left.PulToLeftViewGrouplandroid:id="@+id/pull_group"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.v7.widget.RecyclerViewandroid:scrollbars="none"android:background="#FFFFFF"android:overScrollMode="never"android:id="@+id/rv_hsv_type_content"android:layout_width="match_parent"android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView><includelayout="@layout/include_left_layout"/></pull_to_left.PulToLeftViewGroupl>

Activity中代码:

mRecyclerView = (RecyclerView) findViewById(R.id.rv_hsv_type_content);moved_view = (RelativeLayout) findViewById(R.id.moved_view);pull_group = (PulToLeftViewGroupl) findViewById(R.id.pull_group) ;pull_group.setMoveViews(moved_view);List<String> strings = new LinkedList<>();for (int ii=0; ii<6; ii++) {String str = "";strings.add(str);}mAdapter = new Adapter(strings);mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));mRecyclerView.addItemDecoration(new Adapter.SpacesItemDecoration(0, 50, 0, 0));mRecyclerView.setAdapter(mAdapter);pull_group.setOnPullToLeftListener(new PulToLeftViewGroupl.OnPullToLeftListener() {@Overridepublic void onReleaseFingerToUpload() {for (int ii=0; ii<6; ii++) {String str = "";mAdapter.addItem(str);}mAdapter.notifyDataSetChanged();pull_group.completeToUpload();}@Overridepublic void onStartToUpload() {}});}

include对应布局就是pull_group.setMoveViews…的注入View。

横向加载更多(查看更多)RecyclerView相关推荐

  1. MUI 上滑加载(没有更多数据)页面回弹 - 效果

    MUI 上滑加载(没有更多数据)页面回弹 - 效果 效果图 · 略 查看官方文档对应的 demo效果 即可 参考代码如下: <!DOCTYPE html> <html>< ...

  2. 移动端web页面列表类上拉加载,查看详情,iframe嵌套第三方页面遇到的问题以及解决办法...

    1.移动端上拉加载 网上有很多成熟的插件,比如iscroll.在这里介绍一下用jquery和js写的上拉加载方法.使用原生的去写上拉加载更多需要三个高度去做对比,以新闻类列表举例,首先需要整个dom的 ...

  3. Android框架之路——Glide加载图片(结合RecyclerView、CardView)

    Android框架之路--Glide加载图片 一.简介: 在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech.这个库被广泛的运用在google的开 ...

  4. R和Rstudio中包的安装、加载和查看等操作

    前言 R语言中,R包的安装和加载等操作是使用R包进行数据分析和绘图的基础,尤其是对于R语言初学者具有重要的意义.下面主要介绍一些R包的常用操作命令. 1.R包的安装 #1.从R CRAN 镜像安装R包 ...

  5. 如何用js实现简单的页面html动态加载(“看更多“/页面折叠功能)

    关键: 使用document.createElement函数创建html元素 滤清各元素父子关系并使用appendChild()函数将其联系 下面给出两个示例代码: 示例代码一 注意:该代码使用了Bo ...

  6. 使用Picasso加载网页图片到RecyclerView

    效果图 添加依赖项 compile 'com.android.support:appcompat-v7:22.2.1' compile 'com.android.support:recyclervie ...

  7. BaseRecyclerViewAdapterHelper源码解读(四) 上拉加载更多

    上拉加载 上拉加载无需监听滑动事件,可自定义加载布局,显示异常提示,自定义异常提示. 此篇文章为BaseRecyclerViewAdapterHelper源码解读第四篇,开源库地址,如果没有看过之前3 ...

  8. android官方上拉加载,Android-RecycleView上拉加载更多

    5.0之后 推出的RecycleView来代替ListView,可以说RecycleView和ListView比起有过之而无不及,下面这篇博客主要来实现RecyclerView的上拉加载更多功能. 基 ...

  9. uni-app下拉刷新、上拉加载更多实现

    下拉刷新 下拉刷新文档 在 js 中定义 onPullDownRefresh 处理函数(和onLoad等生命周期函数同级),监听该页面用户下拉刷新事件. 需要在 pages.json 里,找到的当前页 ...

最新文章

  1. 端到端基于图像的伪激光雷达3D目标检测
  2. JavaScript代码规范
  3. SpringBoot @PostConstruct和@PreDestroy使用详解
  4. 论文浅尝 | HEAD-QA: 一个面向复杂推理的医疗保健数据集
  5. php 生产环境调错
  6. python读取数据集前十行_Python读取数据集并消除数据中的空行方法
  7. python调用TensorFlow时报错:FutureWarning: Passing (type, 1) or ‘1type‘ as a synonym of type is deprecated
  8. 为什么C#有委托,而Java没有?
  9. wireless中添加country code的方法(wireless-regdb crda)
  10. Ceph测试工具总结
  11. plsql命令窗口使用
  12. 带妹妹学密码系列4---流密码(ZUC)
  13. 商品库存清单案例(Java)
  14. Maya cmds pymel 单位和轴向设置
  15. 22-09-20 西安 谷粒商城(04)Redisson做分布式锁、布隆过滤器、AOP赋能、自定义注解做缓存管理、秒杀测试
  16. 在maven官网下载maven历史版本
  17. 电子学会2023年3月青少年软件编程python等级考试试卷(四级)真题,含答案解析
  18. 计算机组成与体系结构(一)
  19. 了解AMD处理器的OPN编号
  20. [记录一个bug]ffmpeg转码时间戳-伪代码版流程要点小记[已解决]

热门文章

  1. 《塞尔达传说:荒野之息》开发者演讲
  2. Cocos2d坐标系具体解释
  3. atd与crond的区别
  4. Android managedQuery查询如果加入group by条件(及其猥琐的方法)
  5. Python爬虫大战、 Scrapy分布式原理以及分布式部署
  6. java类成员变量初始化_探讨Java类中成员变量的初始化方式
  7. Speedoffice(word)怎样段落设置首行缩进
  8. 用于自动驾驶汽车赛车中实时最优轨迹规划的顺序凸规划方法(Matlab代码实现)
  9. 紫影龙的编程日记 —— 认识类和对象
  10. android_home,【解决】Environment variable $ANDROID_HOME not found