zoukankan      html  css  js  c++  java
  • 四核驱动的三维导航—淘宝新UI(设计篇)

    前面有一篇博客说到了淘宝UWP的"四核驱动的三维导航—淘宝新UI(需求分析篇)",花了两周的时间实现了这个框架,然后又陆陆续续用了三周的时间完善它。

    多窗口导航,与传统的导航方式的最大的不同点是:

    1. 需要指定目标窗口(target Frame)
    2. 维护上下文关系(context)
    3. Back Stack的维护
    4. 页面间的异步通信
    5. 适配Desktop和Mobile界面
    6. 支持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其实也是一种屏幕适配。

  • 相关阅读:
    HDU5418.Victor and World(状压DP)
    POJ2686 Traveling by Stagecoach(状压DP)
    POJ3254Corn Fields(状压DP)
    HDU5407.CRB and Candies(数论)
    CodeForces 352D. Jeff and Furik
    CodeForces 352C. Jeff and Rounding(贪心)
    LightOj 1282 Leading and Trailing
    Ural 1057. Amount of Degrees(数位DP)
    HDU 2089 不要62 (数位DP)
    HDU5366 The mook jong (DP)
  • 原文地址:https://www.cnblogs.com/ms-uap/p/5543180.html
Copyright © 2011-2022 走看看