(图1)
在Andriod 4中顶部操作栏是导航和功能选项的必争之地,而且Andriod 4设计规范也建议把导航和功能选项放在此处。顶栏位置有利于发现应用的功能:在顶栏,按钮可以很容易被看到,而且永远不会被用户的手遮住。
可是,把按钮放在屏幕的顶部实际上是一把双刃剑:对有些设备来说,顶栏是手指很难触及到的。即使在小型设备上也需要费一番功夫。如果设备再大一点(如很受欢迎的Galaxy Note),要想点击顶栏的按钮,你不得不用上另外一只手。这样一来,不管是多任务操作还是放松随意的使用都会变得艰难。
而且,操作栏占据了屏幕顶部一块非常重要的位置。当用户在学习使用这款应用的时候,可见的功能选项可以给他们提供有效的帮助。不幸的是,用户一旦学会了如何使用,顶栏就会变成“视觉噪声”,而且浪费了屏幕最引人注目、最宝贵的位置。
导航无处不在
如果有一种方法可以让整个屏幕100%只显示内容,同时又允许用户毫不费力的调用功能菜单(不管手指在什么位置,在屏幕什么区域),而且可以轻而易举的点击任何选项,这样的方法是不是很好?是的,这就是“C手势”要做的。
(图2)
用拇指在屏幕任何地方画一个半圆即可调用一个隐藏的菜单,菜单中的选项和顶部操作栏中的相同。菜单出现后,用同一个手指点击所需的选项也是一件很容易的事。
两种菜单设计
我介绍的“C手势”有两个形式不同但一样重要的方案:“滑动—松开”( swipe and release)和“仅滑动”(swipe only)。两个方案调用的菜单在形式上不太一样,你需要选一种适合自己的。“滑动—松开”方案把icon放在菜单选项内部,如上方图2所示。
使用这个方案的的用户可以先在屏幕表面画一个半圆,然后手指移开屏幕。在这里移开手指是很必要的,由于icon在菜单选项内部,不移开手指大部分选项会被遮住,那会造成使用上的不便。
第二种方案只需要滑动一下,不需要移开手指。如下方图3所示。系统识别手势的方法和上面的方案一样。但此时的菜单会随着手指的滑动即时出现在屏幕上(不是弹出)。由于拇指挡住了部分选项,icon需要展示在选项外部才能保证其可见性。
(图3)
你应该选择哪种交互方式?
“仅滑动”方案,拇指和设备时刻处于接触状态,能够即时触发菜单。这一点保证了导航效率:理论上没有“无用功”(no wasted motion)。但是很多被测用户更喜欢icon在菜单内部的设计方案。试用一下附件中的小应用,自己抉择吧。附件中的小应用是这两种方案的合体:它使用“滑动—松开”手势,但把icon放在了菜单选项外面。因此,你可以同时感受两种方案。
提示:谨记,我们提供的小应用调用菜单的滑动手势非常简单,你只要在屏幕上画一个很小的半圆就行,可能比你想象的小得多。我希望这个最简单不过的demo可以在任何设备上运行,不管屏幕大还是小,这种方案都能适用。(我们希望可以完美适用3997种屏幕)。画小半圆的原因是出于对人体解剖学的考虑:大手掌的人画小半圆远比小手掌的人画大半圆容易。
替换操作栏
基本上可以用“C手势”替换目前所有的Android导航栏菜单。也就是说使用导航栏的地方都可以换成“C手势”。正如我在及即将出版的一本书( Android Design Patterns: Interaction Solutions for Developers)中提到的一样,这种很不错的“C手势”,是熄灯模式(lights-out mode,屏幕显示内容为主,不显示导航控件。即隐藏式瑞士军刀风格的导航)即将引领潮流的先声。
另外一个重点是“C手势”几乎可以无限扩展:它容纳的选项qq群营销专家比屏幕上能显示的选项多很多,可能比一级菜单、二级菜单、三级菜单的总和还要多。半圆形菜单的内环部分可以作为切换按钮,点击即可看到更多选项,如下面图4所示,点击中心按钮,在半圆菜单外圈显示更多选项,再次点击返回初始菜单界面。这样,用户就能很轻松地访问8-12个优先级最高的功能。
你可以尝试分别为“滑动—松开”和“仅滑动”两种方案添加子菜单。
(图5)
上图第一排展示的是“滑动—松开”显示子菜单的方式。点击“Favorite”选项,在半圆菜单外圈出现一串星形按钮。用户把拇指移开即可看到子菜单上的功能选项,之后就可以按需点选了。
第二排展示了“滑动—按住”显示子菜单的方式,工作原理和上一中有些相似。拇指在屏幕上画“C”,保持手指接触屏幕,菜单出现后将手指滑动到目标选项上(例如“Favorite”),松开手指后子菜单就会代替原先的主菜单。
要点在于“C手势”有很多种版本,而且子菜单不需要也是半圆形,它可以是一串文本或icon也可以是一个特定的收藏夹。只要保证子菜单出现在“C手势”菜单附近即可。
为什么要用“C手势”?
“C手势”有很多优点:
1、提供沉浸式体验(Immersive Experiences)哪个公关公司做危机公关比
这种模式具有高度沉浸式特性,所有的功能按钮都被隐藏起来,直到你需要的时候才会出现。它可以100%利用安卓设备的屏幕(包含全部3997种),为购物、阅读、看视频、虚拟现实等提供沉浸式体验。
2、最大限度减小手臂应变(Arm Strain)
“C手势”尤其适合大尺寸触屏设备,如即将上市的15-、17-、21-英寸平板电脑。在目前Andriod 4系统导航模式中,点击顶部或底部操作栏需要较大幅度手臂动作,很快就会造成手臂疲劳。相反,“C手势”可以让菜单出现在手指能触及的区域附近,不需要手臂大幅度运动就能完成操作。
3、符合费茨定律(Fitts’Law)
费茨定律指出点击按钮的速度和难易程度与目标的大小和到目标的距离有关。也就是说,在大屏平板电脑上点击一个小按钮必定是一件非常痛苦的事。相比之下“C手势”具有独到之处:它可以在屏幕任何位置调用导航,而且菜单出现的位置永远在手指放置的位置附近。如此一来定位选项的时间就减少了,点击的动作会更加精确和自然。
4、触发动作唯一性
目前看来“C手势”还没用在其他功能上(作者发表文章时,2013.3.25)。因此,使用“C手势”并不会导致使用上的冲突,而且点击菜单以外的任何位置(取消菜单的动作)同样很简单。
强调一下,当用左手操作时,触发动作为“反C手势”。下面提供的源代码和小应用都支持左右手完成操作。
其他建议
“C手势”不一定在屏幕边缘才能被触发。当用户站着使用大屏幕设备时,他可能需要将屏幕倾斜找到一个舒服的姿势。这时,用户可以用手指在屏幕任何位置画个半圆调用“C手势”导航。通常情况下,用户可以用任何一只手指,如食指,来完成这个动作。
“C手势”是很独特的,因为菜单出现的时候伴随着“天然的”动画过渡效果。随着拇指划过屏幕,半圆形菜单也紧接着出现在拇指划过的区域,非常自然。
警告
“C手势”隐藏的很深,并不容易被发现。不过这个缺点可以通过添加水印动画弥补,或者用其他优雅的方式作为引导。给用户一些提示如:“用手指在屏幕任意位置画个”C”。”或者用水印动画在屏幕的不同位置提示几次,就能帮助用户发现这一手势的奥秘。
当用户发现这种手势之后,水印动画就可以永久消失了。“C手势”非常易学,因为我们对这种手势非常熟悉,而且使用时手臂和手指都很放松。
有些人认为“C手势”的缺陷在于它只是人机工程学上符合用户要求,没有映射现实世界中真实的事物(如卷轴或铁锅)。很多设计师喜欢Windows现代 风格的UI设计,其中用到的都是“大手势”(larger gestures)。他们很喜欢那种整条手臂从左滑到右从上滑到下的感觉。还有一些设计师喜欢用替代“大手势”的方法:一种特殊的多点触控手势——如五指轻点,或五指一起捏。
我是不同意这种观点的
尽管人们提出了很多导航方法,而且每个都承诺很好用。但我仍然觉得“C手势”是最自然、最真实、最经济的触摸动作。它是很自然的动作,就像用户在轻挠或抓取屏幕上的内容一样。
不管设备处于什么样的姿态,在什么样的任务场景中,这个滑动动作可以轻易的用一只手完成。为了验证这一观点的正确性,我们还需要扩大被测用户的范围做更多测试。
但是有一点可以明确:不管手势如何变化,在需要的时候从屏幕局部随时调用上下文导航是适用于任何触摸屏设备的功能模型——所以我最大的建议莫过于一定不要忘了这个重要的趋势。
源代码解释
可以想象到这一功能着实复杂,下面的代码只是一个粗略的预览,看的时候关注重点就好。
要做一个完整的应用,你需要先用Android SDK中的GestureBuilder记录自定义“C手势”。详细步骤可以查看Micha Kops的文章: 《Creating a Simple Gesture App With Android》
然后,在 CSwipeActivity 类(class)里,从库(library)中载入自定义“C手势”:
// Load gestures library
mGestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures_cswipe);
if (!mGestureLib.load()) {
// Show toast if gestures library could not be loaded
Toast.makeText(this, R.string.KMsgErrLoadingGestures, Toast.LENGTH_SHORT).show();
}
接下来,建立一个监听器(listener)来监视目标手势(识别“C手势”):
// Register gestures listener
mGestureOverlayView.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
public void onGesturePerformed(GestureOverlayView gestureOverlayView, Gesture gesture) {
onGesture(gestureOverlayView, gesture);
}
});
执行任何手势时都可以用onGesture()判断一下该手势是否满足“C手势”条件。你可以通过对比预测值是否高于某些预定值来判断用户的手势是否满足要求。在我们提供的demo中,我们把预定值设置成一个中间值(middle-of-the-road value)—3D,这个值是试验得出来的,如果数值过低,简单的滑动都有可能意外触发这个功能,如果门槛太高,这个手势就很难被触发。当检测到正确手势之后,应用就会调用特殊的半圆菜单,同时填充预置的选项:
if (prediction.score > 3D) {
// Switch content from gesture overlay view to original content view
mGestureOverlayView.removeView(mContentView);
setContentView(mContentView);
// Inflate the CSwipe control view
final View cSwipePopupContentView = getLayoutInflater().inflate(R.layout.view_cswipe, null);
mCSwipe = (CSwipe) cSwipePopupContentView.findViewById(R.id.cswipe);
我们提供的小应用demo,支持两种方向的“C手势”:向左和向右。可以用下面的代码判断,然后设置菜单锚点的方向:
// Check the orientation of the CSwipe control based on the selected gesture prediction
final String predictionName = prediction.name;
CSwipe.Anchor cSwipeAnchor = CSwipe.Anchor.RIGHT;
if (predictionName.equals(GESTURE_CSWIPE_LEFT_MARGIN)) { cSwipeAnchor = CSwipe.Anchor.LEFT; }
else if (predictionName.equals(GESTURE_CSWIPE_RIGHT_MARGIN)) { cSwipeAnchor = CSwipe.Anchor.RIGHT; }
// Set the CSwipe control anchor according to the selected gesture prediction
mCSwipe.setAnchor(cSwipeAnchor);
让菜单尽可能出现在手势锚点附近,从而呈现出一种菜单伴随手势平滑出现的视觉效果:
// Show the CSwipe control popup window as close as possible to the gesture bounding rectangle
final RectF gestureBoundingRect = gesture.getBoundingBox();
mCSwipePopupWindow.showAtLocation(mCon海尔网络营销转型tentView, Gravity.NO_GRAVITY, (int) gestureBoundingRect.left, (int) gestureBoundingRect.top);
用CSwipe类来启动这个由外圆和内圆定义的特殊半圆菜单。你可以在Widget folder中找到完整的CSwipe.java代码:
public CSwipe(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CSwipe);
mInnerArcRadius = attributes.getDimensionPixelSize(R.styleable.CSwipe_innerArcRadius,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_INNER_RADIUS_DP, getResources().getDisplayMetrics()));
mOuterArcRadius = attributes.getDimensionPixelSize(R.styleable.CSwipe_outerArcRadius,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_OUTER_RADIUS_DP, getResources().getDisplayMetrics()));
总结:
亲爱的读者们,剩下的任务就交给你们了。你可以继续润色代码以提供更多增强功能:提高反应速度;创建平滑的转场效果;调试判断手势的初始值;甚至在学习中随着时间的推移重新编写手势检测的算法,从而最大程度上匹配各种设备型号和用户手掌尺寸。现在,是时候感受一下我们提供的demo了,我想它应该可以体现出“C手势”导航的潜力。
附:demo下载地址:(安装方法同普通安卓APP)
http://media.smashingmagazine.com/wp-content/uploads/2013/02/CSwipeDemo2.zip
作者:Greg Nudelman 翻译:
(原创博文,转载请注明出处)
|