MGTileMenu:一个开源iOS控件的诞生

jopen 12年前
   <p>        英文原文:<a href="/misc/goto?guid=4958346911378927464">MGTileMenu</a></p>    <p>        导读:<a href="/misc/goto?guid=4958346912216600107" rel="nofollow" target="_blank">Matt Gemmell</a> 是欧美知名 iOS/Mac 开发人员,现居苏格兰爱丁堡。Matt 围绕他近期发布的一个开源 iOS 控件 <a href="/misc/goto?guid=4958346913012864110" rel="nofollow" target="_blank">MGTileMenu</a> 写了两篇博文。在惊叹国外顶尖开发人员对细节精益求精的专业态度之余,我们是否也应该反思国内从业人员低水平重复的现状与深层次原因?</p>    <p>        很高兴宣布我的又一个开源 iOS 控件 <a href="/misc/goto?guid=4958346913012864110" rel="nofollow" target="_blank">MGTileMenu</a> 发布了。这个控件基于 iOS 5 开发,使用了 ARC(译者注:<a href="/misc/goto?guid=4958346914541110679" rel="nofollow" target="_blank">Automatic Reference Counting</a>),能提供具有关联性、基于砖形按钮的弹出式菜单,对 Retina 和非 Retian 显示屏都有很好的支持,同时还支持 VoiceOver。MGTileMenu 最初是为 iPad 应用开发设计的,但把它用在 iPhone 和 iPod Touch 应用里也是可以的。</p>    <p>        你可以基于署名授权许可证(Attribution License)免费使用 MGTileMenu,也可以付点费用而免去署名授权协议的限制。MGTileMenu 没有使用其它第三方资源。在 Retina 分辨率下,看起来是这个样子:</p>    <p style="text-align:center;"><a title="MGTileMenu" rel="lightbox[21037]"><img style="width:543px;height:560px;" title="MGTileMenu" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/351d8dff23f133f119e634f335e2318f.jpg" /></a></p>    <p></p>    <p>        弹出菜单每一页会显示最多 5 个图标,而第六个省略号图标用来引出下一页的按钮,你可以拥有任意数量的页面。这里有一个 demo 的视频:</p>    <p style="text-align:center;"> <object data="http://player.youku.com/player.php/sid/XNDIyODM2NzY4/v.swf" width="600" height="450" type="application/x-shockwave-flash"></object></p>    <p>        注意翻页按钮(…)的位置可以通过设置 MGTileMenu 的左右手使用习惯属性而改变,同时这个控件还考虑的对用户手指遮挡区域的留白处理。</p>    <p>        MGTileMenu 提供了委托协议(delegate protocol)以方便开发者对按钮图标、背景(支持图标、渐变色、纯色)的深度定制。</p>    <p style="text-align:center;"><img alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/0391583e9455547e7967ac63e9806a36.jpg" width="534" height="528" /></p>    <p style="text-align:center;">        这是使用了一套表情图标定制的菜单</p>    <p>        MGTileMenu 同时还抛出了各种通知消息(notifications)以方便开发者调用。当然,为了获得最佳的用户体验,我在开发这个控件的时候大量使用了 <a href="/misc/goto?guid=4958346915333482258" rel="nofollow" target="_blank">Core Animation</a> 技术。</p>    <p>        我本着方便开发者调用的初衷设计了 MGTileMenu 控件:它的缺省界面和操控表现已经可以满足大部分场合的调用。此外控件的一些智能化处理也将降低调用者的开发量,例如:它会根据开发者告之的屏幕显示位置,结合屏幕边际距离、设备旋转能因素,综合计算后安排菜单最终显示位置,以避免控件显示在屏幕外等尴尬的结果。随控件附带的 view controller 也是按照方便使用的原则设计了属性、方法及委托协议。总之,你会发现集成 MGTileMenu 到你的项目中是很容易的一件事儿。</p>    <p>        在代码资源里我还放了一个 demo 程序,用来展示如果配置生成一个例子菜单。运行这个 demo 后,在屏幕任意位置双击可以唤出 MGTileMenu 菜单。当然,在你自己的应用开发中,你可以通过单次触碰等更自然的方法唤出 MGTileMenu 菜单。</p>    <p>        <strong>许可证及捐赠</strong></p>    <p>        MGTileMenu 是基于署名授权协议(Attribution License)发布的。同<a href="/misc/goto?guid=4958346916135743777" rel="nofollow" target="_blank">我的其它代码</a>一样,我开发并免费发布这个控件是为了给 iOS 及 Mac 开发社区提供一点贡献,我本人很自豪成为这个社区里的一员。</p>    <p>        <strong>为了支持这个控件的不断更新(同时为了支持我的博客),请考虑捐赠或者购买非署名授权许可证。</strong></p>    <p>        你可以向我的 PayPal 账号 (<code>matt.gemmell</code> at Gmail)捐助,我会非常感谢,并通过未来的博客文章以及代码做出回报。</p>    <p>        如果你不想在你的应用中提供本控件的授权署名信息,请通过我的<a href="/misc/goto?guid=4958346916919436949" rel="nofollow" target="_blank">在线许可证商店</a>购买非署名授权协议。感谢支持!</p>    <p>        <strong>下载代码</strong></p>    <p>        你可以<a href="/misc/goto?guid=4958346917715688639" rel="nofollow" target="_blank">在 github 上下载 MGTileMenu 的代码</a></p>    <p>        <strong>支持,bug 及功能请求</strong></p>    <p>        我不承诺对这个控件提供<strong>任何支持</strong>。哥们,遇到问题你只有靠自己了。当然,你可以通过 <a href="/misc/goto?guid=4958346918505195502" rel="nofollow" target="_blank">github 上的 issue tracker</a> 提交新功能请求。如果想提交 bug 报告,也请通过 <a title="GitHub 如何运作:时间并不决定一切" href="/misc/goto?guid=4958342999982262212" target="_blank">GitHub</a> 的 issue tracker,请务必同时附上你对 bug 的分析及修复方案(要源代码哦)。我想,作为使用者,你一定是一个有能力自行分析并修复问题的合格开发者,对不?同时欢迎在 github 上提交 pull 请求或者补丁申请。</p>    <p>        再啰嗦一次:请不要提交不含分析及推荐修复代码的 bug 报告!</p>    <p>        <strong>聊聊 MGTileMenu 的设计</strong></p>    <p>        设计 MGTileMenu 的初衷是为了发掘一种新的 UI/UX 方式,当用户触摸 iPad 屏幕后,提供具有关联性的可选项或者工具按钮。我在开发一个应用的时候设计了这个控件,后来我觉得有必要把这个控件单独发布出来。</p>    <p>        在此之前,我也做过一些尝试,比如<a href="/misc/goto?guid=4958346920033868075" rel="nofollow" target="_blank">为每一个手指分配工具选项</a>, 但是这次我想做的更加自然,用户体验更加有质感一些。我把最初的想法画在本子上。</p>    <p style="text-align:center;"><img style="width:547px;height:464px;" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/f511a716b186a9eef33c33973421195d.jpg" /></p>    <p style="text-align:center;">        最初的设计草图</p>    <p>        不难看出,最终的成品和上面的草图差别不大。就这样,凭着一个草图和聊聊几笔注释,我打开 Photoshop 开始了第一版设计:</p>    <p style="text-align:center;"><img alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/a9c2554a1e427d25436dd176c9720efa.jpg" width="320" height="320" /></p>    <p style="text-align:center;">        第一版设计</p>    <p>        请注意,我把每一个菜单按钮方块的尺寸设计得和 iPad 屏幕上的应用图标一样大,这样可以给用户提供一个使用习惯上的延续性。但是,最初我在 PS 里面绘制按钮的时候,只是凭感觉拉了一个尺寸,结果正好是应用图标的大小,这完全是一个美妙的巧合!</p>    <p>        看着第一版设计,我总感觉少了点什么:这些散布的按钮应该用什么东西把他们联合起来?很自然的,我想到了在按钮后面叠加一层面板:</p>    <p style="text-align:center;"><img alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/720bfe237435b6ce377258f00000ea2d.jpg" width="320" height="320" /></p>    <p style="text-align:center;">        圆形的背板及连接线</p>    <p>        可是,圆形的背板看起来太单薄了,它承托不出前面按钮矩阵的气场;那些辐射状的连接线看起来也很杂乱,使得功能按钮和关闭按钮直接的关系变很令人费解。这些线必须干掉。</p>    <p style="text-align:center;"><img alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/bff718fe4622f3a9e70e19dd96cc34fb.jpg" width="320" height="320" /></p>    <p style="text-align:center;">        包裹式的背板</p>    <p>        接下来我用了一个可以完全包住所有按钮的圆角背板,感觉还不赖,但是少了几分活力,多了几分沉重。我理想中的背板应该更具动感,以迎合之后我通过 Core Animation 编写的动画效果的气质。</p>    <p style="text-align:center;"><img alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/1533cc09b0844b73b65a90cc3fb2ddc4.jpg" width="320" height="320" /></p>    <p style="text-align:center;">        最终设计</p>    <p>        所以我把圆角背板的尺寸裁剪了些许,这样既整合了四周的按钮,又为中心的关闭按钮提供的背景支撑。事实上在我看来,悬于背板边缘的按钮布局多了几分活泼和有趣的意味。</p>    <p>        在最终设计稿基础上,我通过代码实现了一切。下面是一个运行的实例,呈现的是缺省显示风格:</p>    <p style="text-align:center;"><img style="width:561px;height:579px;" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/3fcbdc6d5e1230272a4dda3417af5e5a.jpg" /></p>    <p style="text-align:center;">        缺省状态</p>    <p>        下面是使用一些定制化背景的效果。</p>    <p style="text-align:center;"><img style="width:561px;height:579px;" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/ec72186d6af98b85d432cde9e4681edf.jpg" /></p>    <p style="text-align:center;">        MGTileMenu 第二页</p>    <p>        我个人对最终的效果很满意。我想这是一个灵活、漂亮、吸引人的控件。接下来让我们看看用户交互设计及动画效果。</p>    <p>        <strong>用户交互设计</strong></p>    <p>        设计伊始,我十分渴望能在用户手势操作上做出一些亮点。当我把自己的手放在 iPad 屏幕上,我发现我们会自然的把手向内侧弯曲,这使得我们的手指在屏幕上的滑动路径是斜向的而不是直上直下的。</p>    <p>        因此,在这个控件的左下角(针对左撇子用户)或者右下角(针对右撇子用户),我安排了一些的留白,这里不能安排按钮,以避免被用户的手遮挡,事实上为了得到最佳效果,我留出了两个按钮的留白位置。</p>    <p style="text-align:center;"><img style="width:512px;height:263px;" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/a9092725e3275a88690d97d8d82374c4.jpg" /></p>    <p style="text-align:center;">        左右手使用习惯可以配置</p>    <p>        这样的留白设计同时也减少了在一页中可显示的最大按钮数量,这其实是件好事,我希望以此激发开发者在他们的应用中减少可选操作项,以体现简洁美。</p>    <p>        注意,在为左撇子用户布局按钮顺序的时候,我不是简简单单把右撇子的按钮排序镜像反转过去的哦。因为我不认为左撇子的阅读、理解顺序也是反着的。当然通过委托协议你依然可以坚持翻转按钮排序如果你认为有必要的话。</p>    <p>        好了,谈了这么多静态的布局和外观,现在我们看看动画效果。基于前面谈到的各种因素,我立刻想到我们需要以下几处动画效果:</p>    <p>        1. 菜单的显示和消失。</p>    <p>        2. 菜单换页时。菜单的显示消失动画很容易想:出现的时候是一个放大加淡入的效果,消失的时候是一个缩小加淡出的效果。难度在从一页菜单切换到下一页菜单的处理,因为同时要替换页面上所有的按钮。</p>    <p>        基于按钮的布局,因为它们看起来都是浮动在背板边缘的,我想到的动画效果是:当用户选择换页的时候,四周的按钮被吸收到中心位置,替换成下一页按钮的图标,在释放回到原位。</p>    <p>        我的最初实现看起来很傻很天真,我用慢动作回放一下动画效果给你们看一下:</p>    <p style="text-align:center;"> <object data="http://player.youku.com/player.php/sid/XNDIyODkxMjI4/v.swf" width="600" height="450" type="application/x-shockwave-flash"></object></p>    <p style="text-align:center;">        同步的吸放动画效果</p>    <p>        后来我在每个按钮的动画效果前都安排的一些滞后,这样出来的效果就好多了:</p>    <p style="text-align:center;"> <object data="http://player.youku.com/player.php/sid/XNDIyODkxMTA0/v.swf" width="600" height="450" type="application/x-shockwave-flash"></object></p>    <p style="text-align:center;">        布进式的吸放动画效果</p>    <p>        而按钮的替换我用了基本的淡入淡出效果,这样的替换看起来不那么唐突。</p>    <p>        上面演示的动画是最终版本的效果。实际上,一开始这些按钮的动画效果是按照从左到右、自上而下的顺序逐个激发的:</p>    <p style="text-align:center;"><img style="width:570px;height:570px;" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/7275bd9562ed9d87a032b899459763ce.jpg" /></p>    <p style="text-align:center;">        按钮动画激发顺序</p>    <p>        可惜这种激发顺序产生的综合效果看起来比较杂乱,尤其是从上一行最右边按钮到下一行最左边按钮的过渡很不协调。后来我尝试了从翻页按钮(…)顺时针激发按钮动画,因为…按钮是用户触发整个切换场景的开端。所以最终的效果就是自翻页按钮(…)上面的那个按钮开始,顺时针绕一圈,逐个按钮吸收、替换、释放。如果配置成左撇子用户,则是反顺序的。</p>    <p style="text-align:center;"><img style="width:560px;height:560px;" alt="MGTileMenu:一个开源iOS控件的诞生" src="https://simg.open-open.com/show/20d40ab604013ace88280b6092922986.jpg" /></p>    <p style="text-align:center;">        最终动画激发顺序</p>    <p>        动画处理上画了我一点时间,但是看着最终的效果还是觉得很值得。</p>    <p>        当然,内部代码以及委托协议里面对按钮的排序还是基于从左到右、自上而下的自然逻辑,这里我就不折腾调用控件的<a title="程序员的本质" href="/misc/goto?guid=4958202204547787659">程序员</a>了。</p>    <p>        <strong>后记</strong></p>    <p>        我个人很享受制作 MGTileMenu 的过程,同样我希望这个东西对你有所帮助,包括这篇文章 — 无论是设计还是编码,我注入的全是爱与激情。 不厌其烦的再次插播广告,请考虑通过捐赠或者购买<a href="/misc/goto?guid=4958346916919436949" rel="nofollow" target="_blank">非署名许可证</a>的方式支持我的代码和博客。</p>    <p>        另外,我透过 MGTileMenu 开发过程的另外一个视角写了另外一篇博客: <a href="/misc/goto?guid=4958346922302770206" rel="nofollow" target="_blank">API Design, and why I designed it the way I did</a>(译者注:此篇稍后翻译) 。对于开发者来说,API 就是他们的用户界面。在那篇博文里,我以 MGTileMenu 为例,阐述了自己对 iOS 及 OS X 组件开发的一些观点。</p>    <p>        预知更多信息,请粉我的推 <a href="/misc/goto?guid=4958346923100828480" rel="nofollow" target="_blank">(@mattgemmell)</a>. Enjoy MGTileMenu!</p>    <p>        英文原文:<a href="/misc/goto?guid=4958346911378927464" rel="nofollow" target="_blank">Matt Gemmell</a>    编译:<a title="伯乐" href="/misc/goto?guid=4958338613453938753">伯乐</a>在线 – <a href="/misc/goto?guid=4958346925363494543" target="_blank">陈远</a></p>