最近给极简日记的交互做了一次大改动,其中关于删除的交互经历了复杂的思考、推敲和设计,感觉值得单独写一篇文章分享出来。
原来在日记列表里,轻点日记条目就是直接进入编辑页面,左划日记条目出现删除、折叠、模糊、分享的操作按钮,经典的 iOS 交互。而切换日期是需要通过拖动底部的加号按钮来完成的,往左拖动就是切换到前一天,往右拖动就是切换到后一天。
自打上线以来,无数用户都反馈过,希望可以左右划动就可以切换日期。但是这个左划的手势,已经日记条目占用了,加入左右划动的话就会造成手势冲突,所以我就一直没改。
直到上周,极简日记上架刚过 3 年,我也有点无法忍受现在的交互了,改!
要想实现这个左右划动切换日期,首先就要把关于日记条目的操作先做修改。最小的改动方式应该就是将 swipe actions 去掉,用长按出现 context menu 来代替,但是长按这个操作需要明确的引导下用户才知道,而且我个人不喜欢长按,感觉速度太慢了。
其实在 demo 阶段的时候,我曾经采用过这个交互方式:点击日记条目出现一个预览页面,页面主体是日记的内容,页面底部是所有的操作按钮。这次我也采用了这个方案,我计算了一下,只有打开编辑页需要多点击一次,而其他操作的步骤和原来是一样的,都是需要操作两下。日记的预览内容直接复用的就是日记的分享样式,头疼的是这些按钮怎么设计……
最开始的想法就是借用 Swipe Actions 的设计,横向排列这些按钮,每个按钮都是圆形的,icon 采用 SF Symbol 和不同的颜色,写出来一看,好丑!
后来,打算将这些按钮排列成一个圆弧形或者扇形,没实际写代码,光是画个草图就感觉还是很丑。也想过做成 iOS 中 Menu 那个样式的按钮菜单,但是受限于屏幕空间,也放弃了。也想过使用 SwiftUI 的 Action Sheet 或者 Confirmation Dialog,但是这个控件需要再弹出一个页面,会有一种中断的打扰,也放弃了。
最终我发现丑的原因就在于 SF Symbol、圆形、不同颜色这三个要素的不协调搭配,索性就把这些都去掉了,就采用最最简单的文字按钮,果然就顺眼好多了。删除按钮放在了最左边,采用红色文字,用分割线和其他操作按钮区分。
说一下这篇文章的重点,删除交互的实现,这是这次改动中花的时间最多的一个地方。
之前的删除交互就是左划日记条目,点击删除按钮,弹出一个 Alert,点击确定后再删除日记。一开始我也想沿用这样的设计,但是首先遇到的问题就是 Alert 不弹出。新加入的预览卡片是通过肘子哥的 SwiftUIOverlayContainer 这个 package 来实现的,就是在日记列表页面弹出一个模态页面,可能是因为这个 package 导致预览页面和父页面的 alert 冲突导致,或者是其他 SwiftUI 什么乱七八糟的 bug,导致 Alert 无法显示。塞翁失马,焉知非福,被逼着变通思路,既然无法显示 Alert,何不如将整个预览页面变成一个 Alert,这样不就完美解决了吗。于是改成点击删除按钮,下面的操作按钮变成取消按钮和确认按钮。
但是这样除了底部的按钮整体没有任何变化,需要在视觉上加强一下删除的状态,于是整个卡片加上了红色的边框,顶部加上了一个垃圾桶的 icon,这样感觉就好多了。
既然顶部有了个垃圾桶,我就在想如果点击删除按钮后有一个日记内容被吸入垃圾桶的动画效果就好了。我的想法是,先将整个日记内容由长方形变成上窄下宽的体型,然后一边收窄一边向上移动,移动的同时整体的透明度降低。我把这个想法交给 Claude 和 ChatGPT,很遗憾都没给出满意的动画代码,甚至都不接近。
这时我就想到了 macOS 上窗口最小化的「神奇效果」,搜了一下这个动画的英文名是 Genie Effect,于是就在网上搜有没有已经用 SwiftUI 实现的例子。好消息是, GitHub 上有两个,坏消息是用 Shader 实现的,必须 iOS 17+ 才可以。下了这两个 repo,默认的动画效果和我的想法有一些不同,都必须修改一下 Shader 代码才可以,于是花了一晚上一上午才调好一点点,但和我理想的效果还差一点,期间也问过 AI,但是 AI 给出的 Shader 代码也都没法用。至此,整个动画就完成了,Siu~~~。最后又给顶部的垃圾桶加上了 bounce 效果,让整个动画更有趣一些。
改成左右划动切换日期后,所有之前的日记操作几乎都重写了一遍,很多页面也都重构了,很自然地出现了很多 bug。比如日期切换错误、分享页面弹出多次、编辑页面内容消失、分享图片尺寸不对等等,因为之前大量使用了通知,很多跨页面的数据是靠通知传送的,导致通知不是发送错误就是接收错误。
还在 TabView 上遇到了坑,图片预览的页面里的 TabView 即使在 App 退出前台时所有的页面都会重建一次,导致 App 回到前台,图片会有闪烁,闪烁的次数和图片的数量是一样的……换了好几个第三方 package 都不行,最后发现 SwiftUIX 的 PageView 就没有这个问题。
而我肯定,还有很多 bug 还没发现。
不过这次的改动,连续三天写代码到后半夜 1 点多,体验到了久违的 coding 心流。而且躺在床上后,一想到这个交互整个的推敲过程,居然兴奋到没有了睡意,直到两点半才睡着。