判断RecyclerView 点击的item中的View是否完全显示,如不完全显示,滑动RecyclerView将View完全显示(仿飞聊app图片查看退场动画方案)

好久不写文章了,工作上遇到一个小问题,自己写的图片查看库,在图片被遮挡时,回退的动画有些瑕疵,究其原因是因为遮挡后坐标拿不到了,原来图片查看效果,
原来退场遮挡时会有抖动.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,我在项目中试了一下,完美解决问题,希望有类似需求的小伙伴可以参考这种方法,解决你的问题,周末愉快~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容