美文网首页Android专题Android应用开发那些事
安卓使用RecyclerView+HorizontalScrol

安卓使用RecyclerView+HorizontalScrol

作者: 奋斗小青年Jerome | 来源:发表于2019-03-05 12:14 被阅读12次

    这个案例是利用竖向的RecyclerView和横向的HorizontalScrollView 实现的一个可横向和竖向滑动的view,

    在模拟器上录了一个效果图,股票APP中常用的效果,下面来分析一下怎么去做这个


    gif效果

    整体布局如下


    布局

    其实看似很简单,也有很多种解决办法,但是我经过试验之后发现这种是性能最好的,因为最外层是个RecyclerView,无任何嵌套,ViewHolder可重复回收利用,界面丝滑,就是需要处理好手势以及细节问题
    这里面几个比较难的部分,总结一下,3个难点问题

    • 1.头布局的HorizontalScrollView如何与下面RecyclerView的Item中HorizontalScrollView实现同步横向滚动
    • 2.当触摸下面RecyclerView的单个Item的HorizontalScrollView时,整个右面布局跟随左右滑动
    • 3.当RecyclerView的右边部分Item滑动到最左边的时候,下拉刷新,部分item位置会错位
    带着上面三个问题,逐个来解决
    • 1.HorizontalScrollView的滑动监听,我们可以去看一下,它有一个onScrollChanged方法的回调,
     @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
        }
    

    首先处理触摸头部时来滚动下面部分的监听,对头部的HorizontalScrollView进行监听,在这个回调的方法里面想办法去滚动item中的每一个HorizontalScrollView就可以了

    • 2.第二个问题,就有点小复杂;由于下部分是个RecyclerView,就涉及到ViewHolder的缓存复用机制,RV的缓存笔记
      我的做法是,将每一个ViewHolder保存下来,并在触摸单个Item的HorizontalScrollView时,在其响应的onScrollChanged方法中,滑动除触摸之外的所有ViewHolder中的HorizontalScrollView
    RecyclerView的ViewHolder中缓存ViewHolder
    if (!mViewHolderList.contains(holder)) {
                mViewHolderList.add(holder);
            }
    
    监听当前触摸的item的viewholder中的HorizontalScrollView滚动,并遍历所有缓存的viewholder,同步滚动其他item的HorizontalScrollView
      holder.horItemScrollview.setOnCustomScrollChangeListener((listener, scrollX, scrollY, oldScrollX, oldScrollY) -> {
                for (int i = 0; i < mViewHolderList.size(); i++) {
                    ItemViewHolder touchViewHolder = mViewHolderList.get(i);
                    if (touchViewHolder != holder) {
                        touchViewHolder.horItemScrollview.scrollTo(scrollX, 0);
                    }
                }
                if (null != onContentScrollListener) onContentScrollListener.onScroll(scrollX);
                offestX = scrollX;//记录滚动的距离(增量)
            });
    

    回到第一个问题,这时候就很好解决了,同样的,遍历viewholder集合,同步移动头部HorizontalScrollView的移动距离
    这里还有一个问题需要解决,当RV可见部分被横向滚动之后,再上下滚动外层的RV,新创建的ViewHolder需要做一个同步的左右滚动

    监听外层RecyclerView的上下滚动,同步滚动内部Item的横向距离(在Item有横向滚动的时候)
    //滑动监听,同步滚动所有item
            refreshRv.setOnSlideListener(new RefreshRecyclerView.OnSlideListener() {
                @Override
                public void onSlide() {
    
                }
    
                @Override
                public void slideStop() {
    
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    List<StockSelectionResultAdapter.ItemViewHolder> viewHolderList = mStockSelectionResultAdapter.getViewHolderList();
                    if (null != viewHolderList) {
                        int size = viewHolderList.size();
                        for (int i = 0; i < size; i++) {
                            viewHolderList.get(i).horItemScrollview.scrollTo(mStockSelectionResultAdapter.getOffestX(), 0);
                        }
                    }
                }
            });
    
    • 3.这个问题的最终原因,还是因为ViewHolder的缓存导致,当RV被下拉刷新之后,重置数据,调用了notifyDataSetChanged,结合ViewHolder缓存,对数据进行重新布局,但是当我在viewholder的creat方法中无论怎么更改当前holder持有的HorizontalScrollView的距离都不生效,还是错位,而且会出现5个错位,其他正常,我看了一下正好是那5个缓存的viewholder的HorizontalScrollView滚动距离设置之后没有生效,我猜想可能是viewholder取出之后,还没有进行布局之前我设置了HorizontalScrollView的滚动距离,所以没有生效,那么怎么监听viewholder的布局呢?
      我找了一圈,只找到getViewTreeObserver().addOnGlobalLayoutListener这个,监听view的layout的listener,不知道还有没有其他方法来监听这个viewholder从缓存中拿出来之后,在什么时机被layout完成
    下面这段代码在viewholder的creat方法中调用,即可解决下拉刷新之后错位问题(这里我用了个flag记录每个holder是否加载完,加载完之后在这里回调,并设置flag为true,这样可以避免这个listener被调用多次,算得上是个小技巧)
      holder.horItemScrollview.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                if (!holder.isLayoutFinish()) {
                    holder.horItemScrollview.scrollTo(offestX, 0);
                    holder.setLayoutFinish(true);
                }
            });
    

    相关文章

      网友评论

        本文标题:安卓使用RecyclerView+HorizontalScrol

        本文链接:https://www.haomeiwen.com/subject/ezrnuqtx.html