【android界面适配】关于viewHolder导致listitem切换横屏之后边距不对的问题总结

    今天解决了一个问题,

1. listview切换横屏之后,item左边距不对导致界面被打孔屏截断

2. 横屏下切换多屏模式之后切换回竖屏,item左边距太大

全部代码在最下边

以我丰富的界面适配的经验来看(哈哈哈),呵,很简单呀,没监听到横竖屏变化还有切换多屏模式的监听呀,so easy。于是查看代码,发现是被其他同事将adapter中getview的时候进行的边距适配逻辑改了,将之前的每一个getview的时候都进行边距适配移到了viewholder实例化的地方去了,于是沟通了一下,得到了如下的结论:

1. 这个边距计算很耗时,占用了基本上getview的一半时间,使界面滑动的性能不达标

2. 如果只在viewholder实例化的地方调用,很明显,当横竖屏切换的时候因为activity已经设置了不在横竖屏切换的时候重新构建,导致viewHolder也实现了复用,于是这些带着竖屏的边距的view就被viewHolder带入到了横屏,导致出现了问题。

这样看来,首先确认一点,我直接拿出来的方法是不可能了,如果我直接拿出来,性能优化又得放进去,界面适配又得拿出来,这样我这下半辈子可能都得改这一个bug了。

在经历了好多的方法测试之后得到了一个最佳的解决方案。

先把测试的方案列出来,然后把却缺点记录一下:

1、 只有第一次viewHolder构建的时候才会进行边距适配,并且因为涉及到的是横竖屏切换还有多屏模式的切换,那我是否可以直接在横竖屏等切换中通过变量控制adapter,在getview的时候通过变量控制,如果经历过横竖屏切换,那我就把getview的convertView清空不就得了嘛,再让他重新创建一次。结果失败了,横竖屏切换之后只有第一个item是对的,其他的还是保持和原来一样,这里面就引发了我的第一个疑问。

2、于是乎第二个方案:其实item的边距都是一样的呀,那我为什么不用一个直接写在布局里面的view来实现边距呢,然后在初始化viewholder的时候直接把这个边距设给这个viewholder,然后借助第一个方案不就行了嘛,看起来问题已经解决了呀,然后,viewholder创建布局,初始化。。。结果又TM失败了,怎么回事儿,又是只有第一个对了,其他的又阵亡了,看来viewholder还是没有给所有的view设置上

3.不信了,第三个方案,我用变量控制边距适配的执行,横竖屏切换我就调用,这样应该可以了吧,然后执行之后再把变量设置回来,但是想了一下不行,getview会走多次呀,这样又是第一个view对了。其他的还是不行,但是我要保证变量不设置回来,那性能问题又回来了,于是方案三夭折在娘胎了

4. 方案四,我通过屏幕的方向设置呢?哎,好像是可以呀,我在每一个viewholder中添加一个方向,在adapter中保存一个界面的整体方向,什么时候切换方向了我再改变这个值,然后再执行边距适配。经过一顿猛如虎的编码,编译,测试,横竖屏切换,哎可以了呀,再切换,哎可以了呀,再来,又可以了,看来我已经解决了,那来个多屏试试,哎也行,来多屏旋转屏幕,卧槽,边距呢,怎么又不对了。。此刻的我崩溃了,下楼抽了一根难受的香烟。就在抽烟的时候灵感突现,没添加分屏的监听呀,好起来了,于是上楼,在分屏变换回调中添加设置变量,再测试,多屏切横屏走起,还是不行,发现我在竖屏的时候进入分屏居然把屏幕的方向变成了2(横屏的参数),神奇呀,老弟,跟我开玩笑呢嘛,时间紧,没时间找系统的人帮忙看一下到底是什么情况了,于是接着想方案5

5、 绕开方向,我直接使用boolean变量控制,你转屏幕我就取反,你进多屏我就取反,此处省略编码,编译,调试走起!好像可以了呀,切了十次,都没事儿了,好找测试验证一下,人多力量大,5分钟之后大哥告诉我不行,我满脑子问号,还他么不行,但是还得开开心心的过去,看一眼,发现这大哥先切了横屏,然后竖屏,然后再横屏,90 270度一顿操作,,然后把listview往上滑,我草,上边的item这帮兄弟是怎么了,你怎么没跟下边的一起动起来呀,终于复现了,我想着大哥,我把问题改成概率的了,我没测出来你测出来了,还得是专业人士呀,于是想了一下,切换的过程中没有在界面中展示的item连续触发了两次就gg了,恩,取反再取反不就回来了嘛,方案五也pass了,

6、 老板,我想换个单子,不接了,我改成概率的了,用户测不出来的,当然这些都是内心的想法,于是神圣而又伟大的方案6诞生了,我取反取反取反,这样不行,那我+1,+1,+1呢,还是原套路,viewholder存一个int型的变量,记录一下之前触发边距适配逻辑时候的tag,然后这次我转一次,我就+1,我进多屏我还+1,但是想了一想,我要+超了怎么办,恩,不能,从用户的角度考虑list他转个100次就够够的了,从稳定性的角度考虑,int型这么大,你能给我跑超界了?于是同样的套路,不一样类型的变量,调试,足足5分钟,终于啥问题没有了,找测试大大,大哥在那转了10分钟也没事儿,好了,提代码,走单咯,

 

疑问1:viewHolder是每一个item一个嘛?我怎么不记得这个知识呢,

疑问2:viewholder到底什么时候初始化,只有当第一个加载过后的item滚出屏幕之后嘛

疑问3:viewholder到底是怎么复用的,几个item复用一个viewholder,界面能装4个item,那第一个和第五个的viewholder是不是一个

疑问4:竖屏下进入多屏为什么orientation会变成横屏的2

 

由于不能公司保密协议,不能贴代码,只能靠想象了,哈哈哈,彩蛋哟,不过还是可以大家讨论一下相关的原理的

为了不让自己忘记这个问题,(说明这个bug对我造成了多么大的影响),为了记录一下,方便哪天有时间自己好好看一下viewholder,为了祖国的繁荣,于是写下了这个不算总结的总结,如果有大佬之后我的疑问,可以帮我解答,要钱没有,以武会友,也希望大家共同去讨论这几个问题。祝大家工作顺利,bug全解

 

一杯茶,一包烟,一个bug解一天

 

现在的APP Banner大多数千篇一律,前几天看到魅族手机上所有魅族自家APP上的Banner效果不错,于是就想着来仿着做一个类似的效果。因此就有了这个库。但是为了使用方便,这个库不仅仅只有仿魅族效果的BannerView 来使用,还可以当作普通的BannerView 来使用,还可以当作一个ViewPager 来使用。使用很方便,具体使用方法和API 请看后面的示例。 ---  左图为魅族APP上的Banner效果,右图是高仿效果。MZBannerView 有以下功能:1 . 仿魅族BannerView 效果。2 . 当普通Banner 使用3 . 当普通ViewPager 使用。4 . 当普通ViewPager使用(有魅族Banner效果)5 . 仿某视频网站Banner效果。Demo APKgif图片有点模糊,可以扫描下方二维码下载APK体验相关博客ViewPager系列之 仿魅族应用的广告BannerView更新日志v1.1.1 : 增加按住Banner 停止轮播,松开开始自动轮播的功能v1.1.0 : fix 在从网上获取数据后,banner 显示 造成 ANR 的bug(如果在onCreate()中设置资源显示则没问题)v1.1.2 : fix 更改数据之后,调用setPages重新刷新数据会crush的bugv2.0.0 :1,add: 添加仿魅族Banner效果,中间Page覆盖两边。 -- 2,fix 部分bug: 添加OnPageChangeListener 回调 pisition 不对的bug.DependencyAdd it in your root build.gradle at the end of repositories:allprojects {      repositories {           ...           maven { url 'https://jitpack.io' }      } }Step 2. Add the dependencydependencies {          compile 'com.github.pinguo-zhouwei:MZBannerView:v2.0.0' }自定义属性属性名属性意义取值open_mz_mode是否开启魅族模式true 为魅族Banner效果,false 则普通Banner效果canLoop是否轮播true 轮播,false 则为普通ViewPagerindicatorPaddingLeft设置指示器距离左侧的距离单位为 dp 的值indicatorPaddingRight设置指示器距离右侧的距离单位为 dp 的值indicatorAlign设置指示器的位置有三个取值:left 左边,center 剧中显示,right 右侧显示middle_page_cover设置中间Page是否覆盖(真正的魅族Banner效果)true 覆盖,false 无覆盖效果使用方法1 . xml 布局文件2 . activity中代码:mMZBanner = (MZBannerViewview.findViewById(R.id.banner);              // 设置数据         mMZBanner.setPages(list, new MZHolderCreator() {             @Override             public BannerViewHolder createViewHolder() {                 return new BannerViewHolder();             }         });  public static class BannerViewHolder implements MZViewHolder {         private ImageView mImageView;         @Override         public View createView(Context cont
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值