这篇文章是senyoung的投稿,分享了微信朋友圈发布图片的拖动和删除功能,希望对大家有帮助。
朋友圈实现原理
我们使用 Android Device Monitor 来分析朋友圈发布图片的界面实现原理。如果需要分析其他应用的界面实现也是采用这种方法哦。
打开 Android Device Monitor,选择DDMS,连接上真机,区域2 就会显示出当前手机正在运行的应用,再点击 区域1,然后新窗口就会显示出当前页面分析的结果,点击 区域3 中的相应控件,区域4 中就会选中对应的控件。区域4 中以菜单的层级关系显示出各控件的关系。
区域4中各参数意义:
eg:(0)FrameLayout[0,0][720,1280]
对应意义:(序号)控件名[x位置,y位置][宽度,高度]
我们这里主要分析与图片拖拽相关的布局实现!通过 4 中的控件层级关系,我们可以画出这样一个大概布局图:
从图中可以看出,微信团队使用了自定义的 GridView 实现了图片的拖拽和删除功能。
准备
以上分析得出微信使用的是自定义 GridView 实现 item 拖拽和删除功能。xxx,现在都什么年代了,还使用 GridView 吗?当然是使用流行的 RecyclerView 实现啦。如果只是单纯地使用 RecyclerView 就能实现的话,那世界就和平。这里还需要使用 ItemTouchHelper 对拖拽进行处理。
ItemTouchHelper
一个让 RecyclerView 支持滑动删除和拖拽的实用工具类
主要方法
使用
自定义一个类继承并实现 I 接口,以下方法必须实现:
实现化 ItemTouchHelper 并关联 RecyclerView
I
ItemTouchHelper 在拖拽和滑动删除的过程中会回调 I 的相关方法:
主要方法
实现过程
先放上最终效果图:
布局文件
自定义 MyCallBack 类继承并实现 Ir 的以下方法:
设置 item 只能处理拖拽事件,并能够向左、右、上、下拖拽
刷新 item
关联 RecyclerView
调整布局
现在运行程序,界面如下:
手动黑人问号??? 仔细研究布局,原来 recyclerView 的高度设置成了wrap_content,因此无论怎么拖动,超出recyclerView的边界的部分就是不会显示滴!那就把高度设置成match_parent咯,重新调整后的布局如下:
再运行一次,我xx,还是不行。这是什么鬼,我不是已经设置了match_parent了吗?这一定有黑科技!经过一番思索,想起了一个不是经常使用的属性:clipToPadding;设置android:clipToPadding=”false”,果然可以。
居然还有这种操作!
android:clipToPadding
设置ViewGroup是否剪切其子View,通俗点讲就是:是否允许ViewGroup在padding中绘制子View。默认情况下,此属性设置为true,即不允许;
另外一个和 clipToPadding 比较相似的属性是:clipChildren;
android:clipChildren
一句话概括就是:是否允许子View超出父View
使用场景有:比如说外卖里的购物车效果
很明显画红色的地方是超出黑色的 View,可以将黑色 View 设置android:clipChildren=”false”,这样子 View 红色部分就可以超出父 View 大小。
还发现了一个比较诡异的问题,地址如下:
设置最后一个 item 不能移动
由以上分析可知,I 的 isLongPressDragEnabled() 可以设置是否支持长按拖拽,默认是 true ,即支持长按拖拽。现在我们要自定义指定哪些 item 可以拖拽,哪些不可以,因此我们需要重写 isLongPressDragEnabled():
取消了支持长按拖拽,就要自己处理 RecyclerView 的触摸事件,具体实现请参考源代码。
在长按事件触发的时候调用以下代码:
最后还需要在 I 的 onMove() 中添加以下代码
还有要在 clearView() 方法里去 notifyDataSetChanged,不然 item 的 position 是没有交换的
设实现拖拽到底部放手删除功能
item 从拖动到放手的主要处理流程图如下:
那么我们应该在哪个地方去判断item是否到达删除区域呢?在前面介绍的方法,有这么个方法:onChildDraw,这个方法就会在item拖拽的过程不断回调并且返回item的偏移量。有了偏移量之后我们就很容易去判断item是否到达删除区域了。
偏移量满足以下条件时,就到达删除区域:
item偏移量>=RecyclerView的高-item底部到RecyclerView顶边的距离-TextView的高
问题来了,我们怎样判断用户在拖动后放手呢?
我们用 boolean up 来标记,当 up 为 true 时手指抬起,false 为初始状态。在getAnimationDuration() 中设置其为true。记得需要在 clearView() 中恢复初始值 false ;
还需要在 I 中暴露个接口 DragListener 给外部,用来提示通知外部什么时候显示删除区域,以及 item 进入删除区域时的文字提示。
相关代码由于过长,这里省略,有兴趣的可以通过原文链接去学习。
图片相关
一看到图片或者说看到 Bitmap,会联想到什么?没错就是OOM!!!对于Bitmap导致的OOM要解决它是很有套路可言的。我们都知道图片压缩分为两种:质量压缩和尺寸压缩。可能有些人对这两个概念不是很清楚!他们的区别是质量压缩并不会改变图片的尺寸,而尺寸压缩则会改变图片的尺寸。当把以文件形式存在在硬盘上的图片,以Bitmap的形式加载到内存中的时候,我就必须进行尺寸压缩,尺寸压缩可以减少内存占用,这样就解决了OOM。详细原理参考文章,地址如下:
对于质量压缩?主要用在图片传输上,用于提高传输速率,就像我们朋友圈发布图片时,它会对图片质量进行压缩,然后再传到后台,所以你在朋友圈看到的图片都不是原图片,都是经过压缩过的。这里推荐一个质量压缩效果和微信差不多的开源库,地址如下:
文末demo已实现图片尺寸压缩,即解决了OOM,也解决了拖拽不流畅问题。
总结
有时候我们看到一个觉得酷炫的功能,很想去实现他。这时候不必匆匆下手。我们自己可以先想一下要是我自己会怎样去实现,然后再用下 Android Device Monitor 大概分析下,更深一步可反编译一下看下源码,看他是怎样实现的,分析两者的优劣。对于这种情形:一个 View1 根据其他 View2 操作的手势或状态的改变而改变的,可以根据这样的套路去想:这个 View2 是否有提供这种状态反馈的方法什么的,我是否能把这个反馈传到 View1等。在不确定这个 View2 是否有你想要的方法时,请查看官方文档,请查看官方文档,请查看官方文档,重要的事件说三遍!比如我的删除区域是根据item的拖拽状态和距离去改变的,那么你就要去找 I 给我提供了什么回调啊,哪些方法可以返回这些东东啊,最后我就写个接口给通知外部。
需要Demo 地址的 关注 私聊吧 这里不能发地址 谢谢
1.《微信分享图片怎么删除不了怎么办?总结很全面速看!Android干货 微信朋友圈发图片拖拽删除》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《微信分享图片怎么删除不了怎么办?总结很全面速看!Android干货 微信朋友圈发图片拖拽删除》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/gl/2972081.html