四核驱动的三维导航—淘宝新UI(设计篇)
前面有一篇博客说到了淘宝UWP的"四核驱动的三维导航—淘宝新UI(需求分析篇)",花了两周的时间实现了这个框架,然后又陆陆续续用了三周的时间完善它。
多窗口导航,与传统的导航方式的最大的不同点是:
- 需要指定目标窗口(target Frame)
- 维护上下文关系(context)
- Back Stack的维护
- 页面间的异步通信
- 适配Desktop和Mobile界面
- 支持Continuum(optional)
本篇博客先说一下前三个问题如何解决。
在从页面A跳到页面B时,单窗口模式下,很简单,只要在页面A中调用系统方法就可以了:
this.Frame.NavigateTo(typeof (PageB));
因为页面A使用的Frame和页面B使用的Frame相同。但是在多窗口(多Frame)时,你需要指定页面B使用那个Frame作为目标窗口。
比如,淘宝首页:
在点击了"淘抢购"频道的入口后,你想在什么地方显示淘抢购的主页面呢?在目前的Taobao UWP中,我们选择在主页的右侧显示(但是考虑到淘抢购的使用频率,我们可能会考虑在下一版中把它作为一个独立的Scenario来对待,也就是说可能要在目前的主页的位置显示)。于是,界面就会变成这样:
这就要求在导航方法中多一个参数来指定具体的位置。按照我们的设计,在Taobao UWP中有以下4个Frame承担具体的导航工作:
Home Frame:作为一个Scenario的首页,必须存在。
List Frame:显示商品列表,可以存在。有些Scenario,它的首页就是一个商品列表,就在Home Frame里显示了,List Frame可以不存在。
Detail Frame:详情页,必须存在。基本上所有的商品,都是要通过详情页来展示具体的商品信息的。当然,在别的Scenario中,如"我的淘宝"场景,可以用此Frame显示别的非商品内容。
Chat Frame:附加页,一般用于显示内置旺信聊天窗口,必须存在。
淘宝首页是显示在Home Frame中的,点击淘抢购入口后,code里都做了什么坏事儿呢?
Nav.To(NavToUrls.RushBuy_Home, mode: NavMode.List_Replace);
其中,Nav是我们自定义的一个导航帮助类,To()是它的静态方法,定义如下:
public static bool To(string url, object param = null, NavMode mode);
参数解释:
- string url:这个是必须的。我们把所有的页面都指定了一个URL,淘抢购的主页的URL定义如下:
public const string RushBuy_Home = "taobao://go/RushBuy/index";
- object param:指定页面间传递的参数。
- NavMode mode:指定导航模式,是一个枚举值,定义如下:
public enum NavMode
{
Default, // show page in scenario frame
Home_Add, // show page in scenario frame
List_Add, // show page in list frame, keep old page (if exists) in back history
List_Replace, // show page in list frame to replace the old page (clear old page in back history)
Detail_Replace, // show page in detail frame to replace the old page (clear old page in back history)
Detail_Replace_Clear, // same as above, also delete page in list frame
Chat_Add, // show page in chat frame, keep old page (if exists) in back history
Chat_Replace, // show page in chat frame to replace the old page (clear old page in back history)
Chat_Replace_Clear, // same as above, also delete pages in list/detail frame
}
每个枚举值都包含有两个信息:位置,方式。如List_Add,下划线前面的"List"表示位置,在List Frame中显示目标页面;下划线后面的"Add"是方式,一共有三种方式:
- Add:如果在目标Frame中已经有其它页面存在,则在已有页面基础上再做一次Navigation,也就是back stack历史中会多出一个记录。
- Replace:如果目标Frame中已有其它页面存在,则"删除"它,也就是在back stack中清空历史记录,然后做一次Navigation,最后back stack中只有最新的页面记录。
- Replace_Clear:同Replace,另外,如果前面的Frame中(除了Home Frame以外),如果有页面存在,则清除它们。
我们逐个解释一下这些参数的用法。
为什么需要Add/Replace方式?举个例子,在淘宝首页,假设用户先点击了天猫:
然后用户又在左侧首页上点击了淘抢购:
由于天猫和淘抢购都是在List Frame中显示,于是淘抢购把天猫覆盖了。此时用户按Back键,希望看到什么?显然不是要回天猫!于是,我们是这样指定淘抢购的导航方式的:
Nav.To(NavToUrls.RushBuy_Home, mode: NavMode.List_Replace);
它指定了淘抢购在List Frame中显示,用Replace方式,也就是清掉前面的天猫的痕迹。
何时用Add方式呢?比如用户在首页点了搜索:
右侧进入了搜索起始页面,用户输入搜索词后按回车,再进入搜索结果页面:
此时用户想改一下搜索的关键字为lumia 950 xl,点击一下搜索结果页上方的搜索框,就会回到搜索起始页。对于这个Scenario,我们需要这样使用导航方法:
1)在首次进入搜索起始页时,使用Replace方式来清空历史:
Nav.To(NavToUrls.Go_Search, mode: NavMode.List_Replace);
2)在进入搜索结果页时,使用Add方式附加搜索结果页:
Nav.To(NavToUrls.Search_Result, mode: NavMode.List_Add);
如此一来,当用户在搜索结果页按返回键,或者点击搜索框(等同于按返回键)时,就会在List Frame中调用Navigation Back方法,回到搜索起始页,因为此时搜索起始页一直在List Frame的历史stack中等候。
何时使用Replace_Clear这种方式呢?对于有些Scenario,有一些特殊的导航需求,主要是为了保证左右两侧窗口的上下文关系。比如店铺:
假设我们先看了店铺简介,现在左右两侧的窗口内容是有上下文关系的。此时,店铺首页在Home Frame中,店铺简介在List Frame中。我们用这个方法来显示店铺简介页:
Nav.To(NavToUrls.Shop_Brief, param: ViewModelData.ShopInfo?.ShopId, mode: NavMode.List_Replace);
现在,左右两侧的情况是:Home Frame <-> List Frame。然后用户在左侧的店铺首页上点击了一个商品,想看该商品的详情,页面就会变成这个样子:
此时左右两侧的情况是:Home Frame <-> Detail Frame。那么刚才的用于显示店铺简介的List Frame哪里去了呢?被清掉了!因为我们使用了这个方式来显示详情页:
Nav.To(data?.H5Url, mode: NavMode.Detail_Replace_Clear);
请大家注意第二个参数,使用了Detail_Replace_Clear方式,表示在Detail Frame中显示详情页,Replace该Frame中以前的内容,并且Clear掉List Frame中的所有页面。于是,店铺简介页面神奇地消失了,因为它不符合现在的上下文关系。当然,此时还需要其他一些手段来隐藏空白的List Frame,比如判断List Frame的Content是否为空。
写累了,喘口气。刚才在写博客做截图时,还发现了个Navigation的bug,顺手给fix了,是调用参数写错了,应该写成Detail_Replace_Clear,但是写成了Detail_Replace,导致现在线上的版本,在店铺页,先点击店铺简介,再在左侧点击全部宝贝,再点击任意商品,此时,随着窗口左滑,左侧是店铺简介,右侧是一个商品详情,上下文关系不对。
本篇博客只是简述了多窗口导航的原理和一些code片段,具体的实现可以根据个人应用场景的需求自己定制,尤其要注意多窗口之间的上下文关系。下次再说说页面间通信和屏幕适配吧,Continuum其实也是一种屏幕适配。
四核驱动的三维导航—淘宝新UI(设计篇)的更多相关文章
- “四核”驱动的“三维”导航 -- 淘宝新UI(需求分析篇)
前言 孔子说:"软件是对客观世界的抽象". 首先声明,这里的"三维导航"和地图没一毛钱关系,"四核驱动"和硬件也没关系,而是为了复杂的应用而 ...
- 魅族MX四核手机转让,二手淘宝上+hi-pda论坛结合使用成功已出
2013-3-14 内容存档在evernote,笔记名"魅族MX四核手机转让,二手淘宝上+hi-pda论坛结合使用成功已出"
- YY淘宝商品数据库设计
http://www.cnblogs.com/mmmjiang13/archive/2010/11/04/1868609.html 前言 这几个月都在做一个通过淘宝API线下管理淘宝店的系统,学习了很 ...
- JAVA爬虫实践(实践四:webMagic和phantomjs和淘宝爬虫)
webMagic虽然方便,但是也有它不适用的地方,比如定向的某个单页面爬虫,或者存在大量ajax请求,页面的跳转请求全都混淆在js里. 这时可以用webMagic结合phantomjs来真实模拟页面请 ...
- 淘宝(新浪)API获取IP地址位置信息
package com.parse; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IO ...
- 基于Bootstrap仿淘宝分页控件实现
.header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...
- 原生js仿淘宝手机购买选项代码
这是一款基于原生js实现仿淘宝手机信息购买选项效果源码,界面整体效果仿照淘宝购物选项设计,点击不同选项还可实时显示不同的价格计算结果,界面简洁大方.美观实用.可兼容目前最新的各类主流浏览器. 在线演示 ...
- Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform
Expression构建DataTable to Entity 映射委托 1 namespace Echofool.Utility.Common { 2 using System; 3 using ...
- 淘宝(阿里百川)手机客户端开发日记第十五篇 JSON解析(四)
解析一个从淘宝传递的JSON (大家如有兴趣可以测试下):{ "tae_item_detail_get_response": { "data": { " ...
随机推荐
- RxJava 学习笔记(一)
最近Android6.0的权限问题,要把之前的APP进行改造,用到了RxPermission框架!之前了解过RXJAVA,但是由于之前项目一直没有使用这个框架,所以也就一直搁置了.正好Rxpermis ...
- [Tool]使用ConfuserEx混淆代码
为了防止程序发布后被一些"坏人"破解,开发者通常会对自己的代码进行混淆.这篇博客将介绍一款使用很广,并且混淆效果也不错的工具ConfuserEx. 新建一个C# 控制台程序,Hel ...
- Kinect开发随笔①——红外扫描仪(Kinect 数据源)
来源于 MVA 的 快速入门:Kinect for Windows v2 开发 的学习随笔 具体内容为上图所示章节内容 章节内全部代码:GitHub地址点我(链接失效,待补档) <Page &l ...
- jQuery九类选择器详解
(1)基本选择器 <body> <div id="div1ID">div1</div> <div id="div2ID" ...
- Javascript 构造函数原型继承机制
我们先聊聊Js的历史,1994年Netscape公司发布了Navigator浏览器0.9班.这是历史上第一个比较成熟的网络浏览器.轰动一时.但是,这个版本的浏览器只能用来浏览,不具备交互功能,最主要的 ...
- 解决ScrollView 嵌套 GridView 单行显示问题
简单重写GridView package com.hh.beauter.my_ui; import android.content.Context; import android.util.Attri ...
- CentOS安装JDK和安装Glassfish
1.首先下载对应CentOS版本的jdk:下载:jdk-7u75-linux-x64.tar.gz 2.下载该jdk到本地,并上传到CentOS系统的opt临时目录下 3.在安装自己下载的jdk之前, ...
- 安卓开发error opening trace file: No such file or directory (2)报错原因
error opening trace file: No such file or directory (2) 这个问题的出现是因为运行的测试机android系统版本和项目api不一致导致. 改成一样 ...
- Idea中包内中的置文件如何发布到编译后的目录中去
1.问题引入: 运行一个maven+springmvc+hibernate的项目的时候出现了下边的错误: Caused by: java.io.FileNotFoundException: class ...
- Programming Language A 学习笔记(二)
1. 语法糖--元组的"名称引用"与"位置引用": (e1,...,en) <=> {1=e1,...,n=en} 类型:t1 * - * tn & ...