人升开发日志#18 | 12/22 优化遇到的坑
这个系列好久没更新了(离目标日渐遥远
这段时间的开发其实遇到了不少问题,不过都没及时记录导致最后也忘记了。
这里记一下新鲜的优化遇到的坑吧。
桌面小部件
之前匆忙写的桌面小部件是不支持分别显示不同清单的,并且还只能显示“所有”。
需要实现在桌面小部件,点击可以直接选择清单。
这里选择了透明Activity+BottomSheetDialog的方案,看上去没打开应用就进行了选择。
实现清单选择功能
第一步:实现透明Activity
透明Style(其实是历史代码):
1 | <style name="Transparent_Activity" parent="AppTheme.NoActionBar"> |
并且这个Activity应该是独立栈,所以将启动模式设置为singleInstance
。
并且在Activity处理Intent传递过来的appWidgetId
参数,实现清单选择。
这里设计布局的时候遇到个小坑:
ImageButton
的background
不能直接设置为?attr/selectableItemBackgroundBorderless
或者?attr/selectableItemBackground
。
当然,这不代表我们不能手动实现Ripple效果:
1 |
|
第二步:设置PendingIntent在点击按钮的时候启动Activity
大概代码:
1 | val categoryChooseIntent = Intent(context, WidgetSelectCategoryActivity::class.java).apply { |
一开始写没留意RequestCode
,写死了一个数字。
然后导致Activity接收到的appWidgetId
和触发事件的Widget对应不上。
解决方法也很简单,让每个Widget的PendingIntent
的RequestCode
不一致即可。
第三步:持久化设置
我这里用的是字符串拼接appWidgetId
为Key来持久化设置。
考虑到可能日积月累,增增删删桌面小部件可能导致插入了很多无用的K-V值,降低SP效率。
在fun onDisabled(context: Context)
方法里还对废弃的设置KV值进行了清理操作。
(该方法的调用时机是清空所有桌面小部件的时候)
第四步:调试失败
理应这样子应该就没问题了。
在Factory里再获取WidgetId
然后去拿相应的设置信息,然后去查询对应的清单数据即可。
但是,实测还是失败。多个Widget还是只会显示同一个设置的清单。
摸索未果,祭出了StackOverflow也查询了半天,才在一个没什么人问津的问题找到了答案:
默认会复用Factory,所以需要在intent填充不同的Data,让其实例化多个Factory
文中用的方法是填充随机数据:
1 | //set random data to initialize new Factory |
其实直接用appWidgetId.toString()
可能更高效:
1 | intent.data = Uri.fromParts("content", (appWidgetId).toString(), null) |
主题色功能
做完清单后,想到要实现将应用内的主题色适配到桌面小部件中:主要就是动态更改一个LinearLayout的背景颜色。
如果只是需要改颜色的话,没什么大问题。
直接这样即可:
1 | views.setInt(<View>, "setBackgroundResource", <ResId>) |
但是我这里的布局用到了Shape实现圆角效果。
对应的类是GradientDrawable
,查询一番,似乎没有什么好办法解决。
这里因为主题色是固定的,所以还能用比较基础的方法实现。
手动实现多个颜色的Shape XML,然后代码判断,用上述方法设置背景即可。
TextView设置android:autoLink
后无法长按/滑动
解决办法可以参考:
https://www.jianshu.com/p/3eed2f4afa07
这篇文章有详细的源码分析,但是最后给出的解决方案处理不完善。比如会依旧无法滑动,长按拦截似乎也有些问题。
https://juejin.im/post/5c373a3451882524bb0b2d23
最后采用的这篇文章给出的解决方案。
人升开发日志#18 | 12/22 优化遇到的坑