美文网首页安卓开发高级UIrecycleview
判断RecyclerView 点击的item中的View是否完全

判断RecyclerView 点击的item中的View是否完全

作者: 庞哈哈哈12138 | 来源:发表于2019-05-25 13:57 被阅读63次
    好久不写文章了,工作上遇到一个小问题,自己写的图片查看库,在图片被遮挡时,回退的动画有些瑕疵,究其原因是因为遮挡后坐标拿不到了,原来图片查看效果, 原来退场遮挡时会有抖动.gif

    然后正好最近飞聊app比较火,主要是我们产品抄了很多头条系app的功能让我也注意到了这个app,看了一下飞聊app 的图片查看,发现他们的在图片放大查看时,做类似微信的交互,回退时,图片的位置改了(其实是recyclerView滑动了)


    飞聊图片退场前会滑动recycleview让图片显示全.gif
    不禁惊叹,哇,还可以这样操作,如果让图片全部显示全,那么退场时图片坐标都可以一一对应,退场动画也就不会抖动了,OK,有了思路我们开始实现
    首先图片可以点击,那么item一定是可见的,我们需要知道imageView getTop 的距离是不是小于0,来确定顶部遮挡,以及getBottom的距离是不是大于RecyclerView的高度 来确定底部遮挡,
    想的太简单.png

    但是在我写完debug时,拿到的距离无论是getTop还是getBottom都是固定的数,列表滑动再点击,拿到的数也不会改,纳尼?这是什么鬼,(后来发现其实是我们基类组件Adapter封装的有问题,正常情况下是可以拿到的)


    getTop和getY拿到的值始终是固定的
    看来这个方案是不行了,于是我把所有view获取坐标的方法都写上打印出来,看看能不能找出规律,果不其然。。。
    重点看getLocalVisibleRect
    先复习一下这几个View获取坐标的方法
    View.getGlobalVisibleRect()

    这个方法会返回一个View是否可见的boolean值,同时还会将该View的可见区域left,top,right,bottom值保存在一个rect对象中,以屏幕左上角为原点

    View.getLocalVisibleRect()

    这个方法和getGlobalVisibleRect有些类似,也可以拿到这个View在屏幕的可见区域的坐标,唯一的区别getLocalVisibleRect(rect)获得的rect坐标系的原点是View自己的左上角,而不是屏幕左上角。其也会调用getGlobalVisibleRect()方法

    public final boolean getLocalVisibleRect(Rect r) {
            final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
            if (getGlobalVisibleRect(r, offset)) {
                r.offset(-offset.x, -offset.y); // make r local
                return true;
            }
            return false;
        }
    

    好了,我们先看正常图片未被遮挡时ImageView 的坐标依次是 Rect(int left, int top, int right, int bottom), 通过getLocalVisibleRect 得到
    而ImageView的高度等于right坐标的绝对值,等于bottom坐标都是996(这个值好诡异)


    正常情况的坐标.png

    上面被遮挡时的坐标 【左 上 右 下】Rect(int left, int top, int right, int bottom)


    上面被遮挡时的坐标.png
    发现top的值变了,其余坐标还是原来样子,
    下面被遮挡时的坐标 Rect(int left, int top, int right, int bottom)
    下面被遮挡时的坐标.png

    发现和正常情况相比 bottom的坐标变了,发现了规律

    1,正常情况下left 和 top 坐标都是0,0 代表我们图片头部上半部分 是始终可见的
    2,上面被遮挡时图片的top坐标会增加,其余坐标不会变
    3,下面被遮挡时图片的bottom坐标会减少,其余坐标不会变

    按照这个规律,那么可以得出下面代码

     /***
         * 解决列表图片被遮挡时 RecyclerView 滑动一段距离 显示出完整的预览图
         * 根据getLocalVisibleRect 相对view自身坐标计算偏移量 只要top和left都是0 right等于view宽度 bottom等于view高度 即图片没有被隐藏
         * 上面被隐藏 top肯定大于0 滑动偏移量即为-top
         * 下面被隐藏 bottom肯定小于 view高度 偏移量即为view高度-bottom
         *
         * 参照 飞聊app 解决方案
         */
        public WBPreviewBuilder setFixHideForRecyclerView(RecyclerView recyclerView, ImageView imageView) {
            if (null != recyclerView && null != imageView) {
                int height = imageView.getHeight();
                Rect rect = new Rect();
                imageView.getLocalVisibleRect(rect);
                if (rect.top > 0 && rect.left == 0 && rect.bottom == height) {
                    //上面被遮挡
                    int offset = rect.top;
                    recyclerView.scrollBy(0, -offset);
                } else if (rect.top == 0 && rect.left == 0 && rect.bottom < height) {
                    //下面被遮挡
                    int offset = height - rect.bottom;
                    recyclerView.scrollBy(0, offset);
                }
            }
            return this;
        }
    
    1,即如果top坐标大于0,并且left坐标等于0,并且bottom坐标和图片高度相等,这时肯定是图片上半部分被遮挡了,我们需要让recyclerView滑动一段距离让view全部显示,这个偏移量也特别好计算 就是top的坐标,但是需要注意因为是图片上半部分被遮挡,我们滑动recyclerView需要是负的值,即
     int offset = rect.top;
     recyclerView.scrollBy(0, -offset);
    
    2,如果left坐标和top坐标都是0,并且bottom坐标小于图片高度,那么这时图片肯定是下半部分被遮挡了,这时滑动的偏移量即

    view的高度减去 bottom坐标

     int offset = height - rect.bottom;
     recyclerView.scrollBy(0, offset);
    

    上面我是计算的ImageView 这个方法可以扩展一下,来计算View是否被遮挡,遮挡的话,计算遮挡距离,然后滑动RecycleView


    很方便也很使用的计算方式.png

    改进后的效果


    改进后的效果.gif

    OK,我在项目中试了一下,完美解决问题,希望有类似需求的小伙伴可以参考这种方法,解决你的问题,周末愉快~

    相关文章

      网友评论

        本文标题:判断RecyclerView 点击的item中的View是否完全

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