Freetao's Blog

让webapp的UI体验更接近原生的小技巧

下拉刷新(图2)和长按选中(图3)是移动端常用操作,也是区分 APP 原生页面和 H5 页面最直观的方法(图1)之一。


下拉刷新

图1:被一眼看出的 H5 页面



下拉刷新

图2:下拉刷新



长按选中

图3:长按选中


专属海报是一款重交互的网页应用,由于依赖阿拉丁(公司内部混合应用框架)提供的文件保存到系统相册和跨应用分享等能力,只允许在宿主 APP 中访问。从视频1可以看出,专属海报尤其依赖划动操作,而划动操作很容易误触发下拉回弹和长按选中事件,这些预期外的操作反馈会给用户注意力带来干扰,所以这里要蔽这两种交互形式带来的操作反馈 —— 既不能为我们所用,又会暴露了我们的身份(H5),就让我们愉快地把它们统统干掉吧。入了 native 的乡,就把自己安安静静地换上 native 的脸 😄



视频1:专属海报操作


阻止下拉回弹

海报选择和全屏预览通过左右划动来实现,为避免划动海报列表完成选择图片操作动作时,在垂直方向的偏差(图4)导致页面整体上下摆动的交互反馈影响到用户关注的焦点,尤其在全屏预览状态中,如果出现上下白边就显得页面感十足/很山寨/“too naive”/“no native“ 😂,所以我们需要禁止页面拉到上下边界出现留白然后回弹的效果。


左右划动角度

图4:划动角度偏差


可以通过为 body 添加 touchmove 属性来达到目的

1
<body ontouchmove=event.preventDefault()>

在出现滚动界面或者需要监听 touchmove 事件的时候(视频中九宫格出现时),执行 js 语句切换开关:

1
2
3
4
// 启用滚动
$(document.body).attr('ontouchmove', '');
// 禁用滚动
$(document.body).attr('ontouchmove', 'event.preventDefault()');

禁用长按选中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*所有元素不可长按选中*/
* {
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
/*输入框可长按选中*/
input,
textarea,
*[contenteditable] {
-webkit-touch-callout:initial;
-webkit-user-select: text;
-khtml-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}

第一段 css 将所有元素长按选中,第二段 css 允许输入框中进行选中操作

1
2
3
4
5
6
// js 捕获菜单事件
// $ = Zepto
$(document.body).bind('contextmenu', function (e) {
// console.log('contextmenu stoped', e.target);
e.preventDefault();
});

通过 js 监听菜单唤起事件并阻止。

也许相比热门的 React Native 等技术方案,这两个小技巧看起来了并不那么“酷”,但 RN 并不一定适合所有业务场景,比如开发验证性质的 webapp ,若因此要求重构 APP 来达到发挥新技术优势的目的,则未免削足适履。

相比以最低成本于解决实际问题、推进业务目标达成,所采用的技术是“酷”还是 “out” 也许并没想象中那么重要,从这个角度来看工程师的价值反而体现在能否 “Get Shit Done”。

这样处理了以后,在 UI 层面离原生体验就接近了一些。下一篇将介绍自己利用 Service Worker 实现离线访问的实践,更进一步地让这个 webapp 使用起来接近原生应用。虽然目前只有安卓版 APP 支持 Service Worker,但对于 iOS 版 APP 的用户即使暂时体验不到优化效果,却也能平稳降级,并不会因优化而带来副作用。

Kainy Guo wechat
微信扫码,或订阅 Feed 解锁更多开发技能。