「四核」驅動的「三維」導航 -- 淘寶新UI(需求分析篇)

前言程序員

孔子說:"軟件是對客觀世界的抽象"。算法

首先聲明,這裏的"三維導航"和地圖沒一毛錢關係,"四核驅動"和硬件也不要緊,而是爲了複雜的應用而發明創造的導航邏輯。說這是發明創造,也不是危言聳聽,由於它徹底突破了傳統意義的頁面導航概念,看完了本博客之後,相信會讓你腦洞大開。固然這也是一種嘗試,只有UWP的出現纔會帶來這種機遇,但願廣大開發者給予指正。windows

上週發佈了淘寶UWP的更新,地址在這裏:https://www.microsoft.com/zh-cn/store/apps/%e6%b7%98%e5%ae%9d/9nblggh6c2cd設計模式

之前淘寶UWP的mobile版叫「手機淘寶」,desktop版叫「淘寶HD」。上週把silverlight版的半殘「淘寶」下線了,把「淘寶」這個應用名稱拿回來了,如今終於把兩者統一爲「淘寶」了。數據結構

隨着UWP的誕生,一個App應該既能夠在狹小的手機屏幕上運行,也能夠在手持式平板電腦上運行,甚至能夠在寬大的桌面電腦屏幕上運行。而對咱們程序員來講,這纔是真正的挑戰。Windows 10,一統天下的宏偉計劃確實給操做系統自己的設計帶來了巨大的挑戰,同時也給UWP應用的開發帶來一樣大的困難,由於它要求你的App能夠運行在全部運行Windows 10的硬件上,而這些硬件有着大相徑庭的屏幕尺寸,從Band,到手機,到平板,到桌面電腦,到Hub。但從另一個方面看,統一的操做系統和UWP卻給用戶帶來了統一的體驗,給整個產業帶來了一樣巨大的利益。app

扯遠了……ide

一維Z軸導航模式函數

首先看看手機上運行的App採用的導航模式:學習

 

這是最簡單的導航模式了,從數據結構上看,是一個簡單的堆棧。A是起始頁面;在A上點擊個按鈕,進入B頁面;在B上點擊個圖片,又進入C頁面。按back鍵從C回到B,再按就回到A。測試

如下是淘寶UWP中,在手機屏幕上運行時的狀況。

首先進入主頁A,而後點擊了"淘搶購"頻道,進入淘搶購的列表頁B,而後在B中點擊了一個列表項,進入該商品的詳情頁面C。

手機屏幕有限,一次只能看一個頁面,當用戶想看其它商品信息時,必須先返回到B頁,而後再選擇另一個條目。

在UWP中,導航必須在Frame類上實現,下面代碼中所示的BackStack,是Frame類中的一個屬性,專門用於保存導航歷史記錄:

 

//
// Summary:
// Gets a collection of PageStackEntry instances representing the backward navigation
// history of the Frame.
//
// Returns:
// The backward navigation stack.
public IList<PageStackEntry> BackStack { get; } 

 

當用戶按了back鍵時,你就能夠簡單地用Frame.GoBack()方法來返回到上一頁了。

在Z軸導航模式中,咱們使用App.xaml.cs裏建立的Frame來作全部頁面的導航容器。

 

Frame rootFrame = new Frame();
Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(PageA));

調用Frame.Navigate(typeof(PageA))時,會把Page A做爲該Frame的Content,同時,這個Frame的值會傳送到Page A的Frame屬性中,二者是一回事兒,是爲了方便再次Navigation時使用。好比this.Frame.Navigate(typeof(PageB)),這裏的this其實是Page A的實例,而this.Frame就是App.xaml.cs裏建立的rootFrame。

Z軸導航的實際UWP的例子不少,如網易雲音樂。Windows Store應用商店App是另一個例子,它的內容也是可擴展的,就是說在窄屏上,能夠一行列出4個項目,在寬屏上能夠根據屏幕寬度列出5~8個項目。還有一個例子就是著名的必應詞典Win10版啦,也是用了一個Frame搞定全部事情。

用這種模式最忌諱的事情是: 當應用場景稍微複雜一些時,也就是頁面較多(8個以上),有可能產生交叉跳轉,可能會形成用戶迷失;而在code方面,形成後退棧愈來愈大,不過這仍是小事情。只要單個Frame的導航能知足你的應用場景就能夠。

舉例來講,若是我在必應詞典裏的背單詞模塊中,想查一個詞,但不想跳轉到search頁,而是想在屏幕右側滑出一個區域來顯示該單詞的詞典解釋,那就須要兩個Frame來完成這個要求了。

不一樣的導航模式,對界面設計的要求是不一樣的,這一點請designer注意。在Z軸單頁模式中,只須要專一每一個頁面的設計便可。但在後面的複雜導航模式中,只這樣作就不夠了。

一維Master/Detail導航模式

在寬大的桌面電腦屏幕上,上面那種在手機的窄屏界面的展現方式是不可接受的。以下圖的Windows 10中的設置頁面,它的窗口是可縮放的,可寬可窄,爲所欲爲。在窄窗口中,顯示一頁的內容;在寬窗口中,side by side地顯示兩頁的內容,合理利用屏幕空間,同時簡化了用戶的操做: 用戶能夠在右圖中的左側列表控件中任意點擊感興趣的條目,在右側能夠馬上獲得響應;可是在左圖中,用戶點擊了Display,進入詳情頁,必須點back鍵回到列表框,才能再進入另一個條目。

 

咱們再來看看ITHome - IT之家UWP的界面:

整個屏幕分紅三列,最左側的窄條Vertical Menu Bar,中間偏左部分的資訊列表,右半部份的資訊詳情。能夠說這是一個標準的寬屏設計模式,易於理解,易於操做,適合推廣使用。

它對應的XAML應該是這個樣子:

 

 1 <Grid Background="{ThemeResource WhiteColorBrush}">
 2     <Grid.ColumnDefinitions>
 3         <!--vertical menu bar-->
 4         <ColumnDefinition Width="48" x:Name="menuCol"/>
 5         <!--list page container-->
 6         <ColumnDefinition Width="2*" x:Name="leftCol" MinWidth="360"/>
 7         <!--detail page container-->
 8         <ColumnDefinition Width="3*" x:Name="middleCol"/>
 9     </Grid.ColumnDefinitions>
10 
11     <common:VerticalMenuBarControl x:Name="menuBar" Grid.Column="0"/>
12 
13     <!--list content in this frame-->
14     <Frame x:Name="leftFrame" Grid.Column="1"/>
15 
16     <!--detail content in this frame-->
17     <Frame x:Name="rightFrame" Grid.Column="2"/>
18 </Grid> 

 

Column-0的寬度爲48 epx (effective pixel),在點擊了上方的漢堡控件展開菜單後,這個寬度能夠調整爲120左右。

Column-1和Column-2的常規比例爲2:3,可是當窗口太窄時,Column-1的寬度有個限制MinWidth="360",避免裏面的內容沒法以合理方式展現。固然也能夠設置一個MaxWidth="720",避免太寬時橫向拉伸太難看。

關於epx的概念,請看這裏:https://msdn.microsoft.com/windows/uwp/layout/design-and-ui-intro 。改天把這篇東西翻成中文給你們洗洗腦吧。

這種設計適合於簡單的二級內容應用場景,想看三級片是不行的了。如今市面上大多數的UWP,均可以用這種方式來實現,如微博UWP就是另一個典型。

若是這樣作的話,是否能讓mobile和desktop兩個device使用同一套UI代碼呢?固然能夠,不然就不能叫作UWP了,只是須要咱們多作一點點事情而已。具體須要作什麼事情,咱們在另一篇博客中(關於Win10 Mobile Continuum的使用方式)會詳細說明。

二維(Z+X)導航模式

用上述的master/detail模式,雖然能夠充分利用屏幕,可是隻適合於場景較爲簡單的應用,如新聞類,閱讀類。下面咱們看一下稍微複雜一些的應用,好比旺信UWP。先看看截圖得到感性認識:

聊天主頁,左側展現好友列表:

 

右側窗口爲具體聊天頁:

 

最右側的浮出窗口爲輔助的設置頁面,基本是popup類型的信息:

 

它的主控頁的XAML是這樣寫的:

 

<Grid Background="{ThemeResource WXWhiteColorBrush}">
    <Grid.ColumnDefinitions>
        <!--vertical menu bar-->
        <ColumnDefinition Width="48" x:Name="menuCol"/>
        <!--list page container-->
        <ColumnDefinition Width="2*" x:Name="leftCol" MinWidth="360"/>
        <!--detail page container-->
        <ColumnDefinition Width="3*" x:Name="middleCol"/>
    </Grid.ColumnDefinitions>
    <!--left side vertical menu bar-->
    <common:VerticalMenuBarControl x:Name="menuBar" Grid.Column="0"/>

    <!--list content in this frame-->
    <Frame x:Name="leftFrame" Grid.Column="1"/>

    <!--detail content in this frame-->
    <Frame x:Name="middleFrame" Grid.Column="2"/>

    <!--popup content in this frame-->
    <Grid x:Name="rightFrameGrid" Grid.Column="0" Grid.ColumnSpan="3">
        <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*"/>
           <ColumnDefinition Width="500" x:Name="rightCol"/>
        </Grid.ColumnDefinitions>
        <Rectangle Grid.Column="0" Fill="Black" Opacity="0.5"/>
        <Frame x:Name="rightFrame" Grid.Column="1"/>
    </Grid>
</Grid> 

 

  • 最左側的是vertical menu bar
  • 第二列是leftFrame,用於顯示主要Scenario的主頁面
  • 第三列是middleFrame,用於顯示每一個Scenario的詳細頁
  • 最右側是rightFrame,用一個grid承載。這個grid用於遮蓋後面的menu bar, left Frame, middle Frame,造成性感的半透明遮罩效果;right Frame用於配置頁面的展現。

在旺信UWP中,咱們使用了三個Frame作navigation。在子模塊開發前,就實現了一個導航framework,使得每一個業務模塊的開發者只須要完成本身的頁面開發,而後直接調用該framework提供的導航方法便可。

固然,這裏的導航再也不是this.Frame.Navigate()那麼簡單,可是也沒複雜到哪裏去,也就是多加了一個參數而已,叫作that.Nav.To(page, left|middle|right),由後面那個參數指定你將要展現的頁面在哪一個frame裏出現。這樣作的基本條件是,作好需求分析,仔細梳理頁面之間的邏輯關係,使得每一個頁面都在一個預訂的frame裏展現。

旺信的導航邏輯能夠抽象成這個樣子:

具體是這樣運行的:

  1. 用戶登陸旺信後,首先展現的是聯繫人頁面,命名爲A1;
  2. 用戶分別和三個聯繫人聊天,會使用X軸導航方式,在右側依次展現三個聊天頁面,A2/A2'/A2";在Middle Frame中,用了Z軸導航,承載三個頁面。
  3. 用戶在A2時作了兩次配置修改,使用X軸導航方式,依次出現了A3/A3'兩個頁面;在Right Frame中,用Z軸導航承載兩個頁面。

 因此,此應用的導航是X+Z的二維模式。這種模式要求interactive designer對該應用的業務很是熟悉,上下文處理得很流暢,不然會有跳躍感。而對於user experience designer,更多地要考慮兩個頁面之間的差異和聯繫,和單頁設計的感受徹底不一樣,兩個頁面既不能長得徹底不一樣(由於有上下文關係),又不能看着差很少,覺得是讓用戶玩「找出不一樣處」的遊戲,由於有上下級關係。

淘寶UWP的應用場景分析

迄今爲止,咱們遇到的最複雜的UWP就是淘寶了。打橋牌的人知道,橋牌是叫牌難,打牌難,計分難,發牌好像最簡單;淘寶是設計難,實現難,測試難,使用起來但是爲所欲爲。

下面咱們先來看一個常見的用戶購物行爲:

  1. 打開淘寶首頁,點擊淘搶購
  2. 進入淘搶購,點擊一個水果商品
  3. 進入詳情頁,點擊店鋪按鈕
  4. 進入該水果的店鋪,點擊了另外一個水果
  5. 再次進入詳情,加入購物車,而後從超級按鈕跳轉按鈕中進入購物車
  6. 在購物車中突然看到了一件之前收入的衣服,還沒下單,因而點擊當即購買按鈕
  7. 進入訂單頁,發現送貨地址應該修改一下,點擊了地址控件
  8. 進入地址選擇頁,發現沒有本身想要的地址,因而點擊地址管理按鈕
  9. 進入地址管理頁,添加好了新地址,想看看之前的訂單的送貨地址有沒有搞對
  10. 進入個人淘寶,點擊個人訂單按鈕
  11. 進入訂單管理,增長了一個新的發貨地址
  12. 後面一系列折騰,整個購物過程通過了50屢次頁面跳轉,歷時1小時……

琳琅滿目的商品,讓人流連忘返,迷失於虛擬的貨架之間。可是做爲UWP開發者,咱們不能迷失,要理智,理智,理智……老闆,那個快遞費能不能便宜些,再送一個贈品……迴歸理智!

之因此有超級跳轉按鈕的設計,是由於你不可能讓用戶back無數次後才能找到購物車頁面,就好像在超市裏你必須推着一個購物車,能夠隨時放置商品,而且能夠有無數通道通向收銀臺同樣。

下圖演示了此次購物行爲的頁面跳轉過程(篇幅有限,圖片較模糊,見諒):

讓咱們來仔細分析一下這個常見的購物行爲。

第一眼看上去,我丂!頁面是能夠亂跳的!根本不是普通的App那樣的進棧出棧的規矩,看上去像是一種網狀關係。再仔細看看!怎麼好像"詳情"頁出現了不少次呢?

在網購中,詳情是購物的關鍵環節,圖片,價格,評價,快遞,等等,它能夠很大程度決定是否馬上剁手。

懷着剁手黨的激動心情,咱們把詳情用藍色標記一下,變成以下圖:

均可以從哪些地方進入詳情頁呢?順藤摸瓜找上游業務鏈,那就是淘搶購,購物車,店鋪。還有不少其餘頁面能夠進入詳情,篇幅有限,不一一列出,好比天貓,聚划算等等。

因而乎,咱們把詳情的上游業務標記成橙色的,以下圖所示:

這裏要注意,店鋪雖然在下圖中,處於詳情的下游,可是從真實場景看,店鋪的概念顯然是大於詳情的概念的,因此它實際是詳情的上游。那個連接只是系統提供的一種方便的跳轉而已。

咱們還能夠繼續剛纔的思路,看看更遠端的上游和下游是什麼?

先看上游,主頁是一個確定的入口;進入淘寶後,也能夠不幹別的,直接進入購物車,所以咱們把購物車從橙色變爲更高級的紅色;個人淘寶是和主頁、購物車並列的入口,也標爲紅色;地址管理的scenario很是特殊,能夠做爲一個獨立的業務,所以也標爲紅色。

再看下游,詳情後面緊跟着的業務應該是確認訂單和支付,固然也能夠先和商家討價還價,進入旺信聊天頁面,這些個下游頁面咱們標記爲綠色的。以下圖所示:

圖中出現了4種顏色,紅色,橙色,藍色,綠色,也就是說,淘寶的絕大部分業務流程,均可以以詳情爲核心,串聯起先後一共3~5步,成爲業務鏈。而每條業務鏈,就是一個Scenario!

4色定理,怎麼讓我想起了微軟大田村的logo呢?

OK,讓咱們照着這個思路,回過頭瀏覽一下淘寶中的全部頁面,大概能總結出如下幾種scenario:

  • Home->H5(如天貓,聚划算)->詳情->旺
  • Home(猜你喜歡)->詳情->旺
  • Home->RushBuy->詳情->
  • 購物車->詳情->
  • 店鋪->詳情->
  • 個人淘寶->H5->詳情->
  • 個人淘寶->設置[list]->關於[detail]->版權信息[chat]
  • 個人淘寶->訂單管理->詳情
  • Home->搜索[list]->詳情[detail]->[chat]
  • 消息(物流)->物流列表[list]->查看跟蹤[detail]
  • 消息(商戶)->[chat]
  • 收貨地址管理->ADRU
  • ……

還有一些分支,處於第3層和第4層,我沒有列出來,不過重要。以上這些足夠咱們整理出一個合理的需求分析了,以下示意圖:

 

也就是說,主頁、店鋪、購物車、個人淘寶、地址管理等,均可以做爲後續一系列業務的入口看待,咱們把它們叫作Scenario.Home;

淘搶購、搜索、訂單管理、天貓、聚划算等,都是一種業務頻道,引導用戶更方便快捷地購物,咱們稱之爲Scenario.List;

詳情是業務核心,成爲Scenario.Detail;

後面的業務環節能夠叫作Scenario.Chat,裏面能夠放旺信聊天頁,也能夠放下單頁等等。

淘寶,必須作成四核的,須要4個Frame參與導航,才能符合咱們通過縝密需求分析得出的完美業務模型。

因而,咱們能夠把業務抽象成這個樣子:

 

  • A是一個Scenario的名字;
  • 1/2/3/4分別是四核導航的4個Frame;
  • A1/A2/A2'/A2"/A3/A4/A4'是這個scenario所涉及的頁面,後面的序號表明它們應該在那個Frame上顯示,若是須要的話,在2/3/4三個frame上均可以作傳統的Z軸導航。好比在淘搶購中,在Frame 2上點擊一個商品,會在Frame 3上顯示一個詳情;在Frame 2上點擊另外一個商品,在Frame 3上就會顯示另外一個詳情。

 

三維(Z+X+Y)導航模式

 

若是你沒看懂前面說的二維(Z+X)導航模式,那就goto前一章節從新看。若是看懂了,那下面的東西就很容易理解了,就是在那個基礎上多加了一維Y軸導航。

我們仍是看圖說話吧,請看下圖:

 

從上到下,一共三層(能夠是N層)淡藍色的面板,每一層表示一個scenario的內部navigation,這一點與前面說的二維導航模式相同,只不過是多了一個frame 4。具體用幾個frame,是由這個App的Scenario決定的,原則上講,用的Frame的數量越少,對系統的performance越有利,code寫着也會簡單些。

淡藍色的面板的數量是隨着用戶navigation的深刻而增長的,隨着按下back鍵而減小的,能夠把藍色的面板定義爲Scenario類。在下面這張圖中,用戶首先在最下面的Scenario A中暢遊了6個頁面(A1,A2,A2',A3,A4,A4'),其中A1->A2作了X軸導航,也就是切換了Frame;在Frame 2中作了Z軸導航,而後從A2->A3作了X軸導航,而後再次X軸導航到A4,在Frame 4中作了最後一次Z軸導航以後,發現了一個神奇的按鈕,切換到了Scenario B,也就是到了第二層面板。以此類推,最後到了Scenario C中,又搞了一些事情。

此時,在Frame 1的導航歷史中,有3個頁面,A1/B1/C1;在Frame 2的導航歷史中,有7個頁面,A2/A2'/B2/B2'/C2/C2'/C2";在Frame 3的歷史中有個3個頁面,A3/B3/C3;在Frame 4中有7個頁面,A4/A4'/B4/B4'/B4"/C4/C4'。

用下面兩個類能夠表示以上數據模型:

public class Scenario
{ 
  public FrameSlot HomeSlot; 
  public FrameSlot ListSlot; 
  public FrameSlot DetailSlot; 
  public FrameSlot ChatSlot; 

  public
Scenario(Frame scenarioFrame, Frame listFrame, Frame detailFrame, Frame chatFrame, string url)   {     this.HomeSlot = new FrameSlot(scenarioFrame);     this.ListSlot = new FrameSlot(listFrame);     this.DetailSlot = new FrameSlot(detailFrame);     this.ChatSlot = new FrameSlot(chatFrame);     this.Url = url;
  } }
public class FrameSlot {   public Frame frame; // current frame   int depth = 0; // navigation times }

在Scenario類的初始化函數中,從外面指定了Frame的實例,也就能夠保證不一樣的Scenario實例能夠共享同一組Frame。

而這些Frame,能夠這樣在XAML中定義:

<Grid x:Name="gridRoot" SizeChanged="gridRoot_SizeChanged">
  <Grid.ColumnDefinitions>
  <!--vertical menu bar-->
    <ColumnDefinition Width="64" x:Name="menuColumn"/>
    <ColumnDefinition Width="*" x:Name="contentColumn"/>
  </Grid.ColumnDefinitions>
  <localControls:VerticalMenuBarControl2 x:Name="menuBar" Grid.Column="0"/>   <!--for content page-->   <Canvas x:Name="panel" Grid.Column="1">     <Frame x:Name="homeFrame" Canvas.ZIndex="10"/>     <localControls:VerticalSeperatorControl x:Name="listSep"/>     <Frame x:Name="listFrame" Canvas.ZIndex="20"/>     <localControls:VerticalSeperatorControl x:Name="detailSep"/>     <Frame x:Name="detailFrame" Canvas.ZIndex="30"/>     <localControls:VerticalSeperatorControl x:Name="chatSep"/>     <Frame x:Name="chatFrame" Canvas.ZIndex="40"/>   </Canvas> </Grid>

 

從XAML中能夠看到,最左側是個Vertical Menu Bar;右側是個Canvas面板。之因此使用Canvas面板,是由於這個panel類型最簡單,能夠任意調整裏面Frame的位置。其它的panel,如Grid, StackPanel, RelativePanel等等都有本身的一套Arrange Children的算法,咱們並不須要。固然,你也能夠本身從panel類派生出一個MyTaobaoPanel類,來組織這4個Frame。

好了,到目前爲止,咱們通過需求分析,找出了合理的模型,制定了基本類和界面邏輯,下面能夠着手開發了……此處略去10000字的開發過程……最後的樣子以下面的截圖所示:

主頁:

 

在主頁上點擊了淘搶購:

 

在淘搶購中點擊了第一個商品:

 

在詳情中點擊了旺旺:

 

在詳情中點擊了店鋪:

 

在左側的超級菜單中點擊了個人淘寶:

 

在個人淘寶中點擊了設置:

 

頁面太多了,上百種navigation的組合路徑,一網打盡!

如今各位看官可能明白了,「四核」指的是4個Frame參與頁面展現與導航,」三維「指的是在三個維度上的導航方向,一維是在一個frame上的Z軸棧式導航,二維是在兩個frame以上的橫向導航,三維是在兩個Frame以上的橫向導航,再加上虛擬層之間的Y軸導航,切換場景至關於OS的進程切換,只不過是棧式的。

孔子還說:"完美的抽象不能決定軟件的成功與否,但能判別開發者的素質。"

老子也說:"好的開發者是一個軟件成功與否的基石。"

莊子說:……哎,讓莊子喝口茶水吧,實在編不下去了,意思大家都知道的,你們努力提升本身的職業素質吧,多學習,多觀察,多思考,多實踐,更好地抽象這個世界。

相關文章
相關標籤/搜索