張高興的 UWP 開發筆記:漢堡菜單進階

来源:http://www.cnblogs.com/zhanggaoxing/archive/2016/12/24/6218717.html
-Advertisement-
Play Games

不同於Windows 8應用,Windows 10引入了“漢堡菜單”這一導航模式。說具體點,就拿官方的天氣應用來說,左上角三條橫杠的圖標外加一個SplitView控制項組成的這一導航模式就叫“漢堡菜單”。 本文討論的是如何實現官方的這一樣式(點擊後左側出現一個填充矩形),普通實現網上到處都是,有需要的 ...


  不同於Windows 8應用,Windows 10引入了“漢堡菜單”這一導航模式。說具體點,就拿官方的天氣應用來說,左上角三條橫杠的圖標外加一個SplitView控制項組成的這一導航模式就叫“漢堡菜單”。

  本文討論的是如何實現官方的這一樣式(點擊後左側出現一個填充矩形),普通實現網上到處都是,有需要的朋友自己百度下吧。

  下麵將介紹兩種不同的實現方法,第一種最簡單的方法是直接使用 Template 10 模板,第二種就是純手寫了。

 

  若有什麼不正確的地方望指正,大家共同討論。

 

  1. Template 10 模板

  使用 Template 10 模板可以快速建立出應用的框架,簡單快捷。(幫助文檔 https://github.com/Windows-XAML/Template10/wiki )

  要使用 Template 10 首先點擊 Visual Studio “工具”菜單中的“擴展與更新”,搜索並安裝 Template 10(簡化搜索可以直接輸入t10)

  安裝完成需要重啟,重啟後按下圖找到項目模板新建即可,使用很簡單,幫助文檔連接也在上方給出。

 

  2. 手寫

  先分析一下界面的構成,暫時不看標題欄,由一個設置了 Canvas.ZIndex 的 Button 和一個 SplitView 構成。SplitView.Pane 中又包含了兩個ListView(一級菜單和二級菜單)。ListView 里的每個 Item 又由 Rectangle,FontIcon,TextBlock 組成。見下圖

  構成清晰之後實現的思路大概也就清晰了。下麵給一個簡單的Demo,解決方案結構如下。(相應的註釋在程式中給出)

  先創建一個NavMenuItem類

using System;
using System.ComponentModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;

namespace HamburgerDemo
{
    class NavMenuItem : INotifyPropertyChanged
    {
        // 記錄圖標字體
        public FontFamily FontFamily { get; set; }
        // 圖標的C#轉義代碼
        public string Icon { get; set; }
        // 標題
        public string Label { get; set; }
        // 導航頁
        public Type DestPage { get; set; }
        // 用於左側矩形的顯示
        private Visibility selected = Visibility.Collapsed;
        public Visibility Selected
        {
            get { return selected; }
            set
            {
                selected = value;
                this.OnPropertyChanged("Selected");
            }
        }
        // 雙向綁定,用於更新矩形是否顯示
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

  

  主頁面框架代碼

<Page
    x:Class="HamburgerDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HamburgerDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <!--菜單的數據模板-->
        <DataTemplate x:Key="DataTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="48" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <Rectangle Fill="{ThemeResource SystemControlBackgroundAccentBrush}" 
                           Visibility="{Binding Selected, Mode=TwoWay}" 
                           HorizontalAlignment="Left" Width="5" Height="48" />
                
                <FontIcon FontFamily="{Binding FontFamily}" Glyph="{Binding Icon}" Foreground="White" 
                          VerticalAlignment="Center" 
                          Margin="-2,0,0,0" Width="48" Height="48" />

                <TextBlock Grid.Column="1" 
                           Text="{Binding Label}" Foreground="White" 
                           Margin="12,0,0,0" VerticalAlignment="Center" />
            </Grid>
        </DataTemplate>
        <!--ListViewItem樣式定製-->
        <Style x:Key="NavMenuItemContainerStyle" TargetType="ListViewItem">
            <Setter Property="MinWidth" Value="{StaticResource SplitViewCompactPaneThemeLength}"/>
            <Setter Property="Height" Value="48"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="UseSystemFocusVisuals" Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <ListViewItemPresenter ContentTransitions="{TemplateBinding ContentTransitions}"
                        Control.IsTemplateFocusTarget="True"
                        SelectionCheckMarkVisualEnabled="False"
                        PointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}"
                        PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
                        SelectedBackground="Transparent"
                        SelectedForeground="{ThemeResource SystemControlForegroundAccentBrush}"
                        SelectedPointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}"
                        PressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}"
                        SelectedPressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}"
                        DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
                        HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                        ContentMargin="{TemplateBinding Padding}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Page.Resources>
    
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <!--漢堡菜單開關-->
        <Button Name="PaneOpenButton" 
                FontFamily="Segoe MDL2 Assets" Content="&#xE700;" Foreground="White" 
                Background="{Binding BackgroundColor}" 
                Width="48" Height="48" 
                VerticalAlignment="Top" Canvas.ZIndex="100" />

        <SplitView Name="RootSplitView" 
                   DisplayMode="CompactOverlay" 
                   CompactPaneLength="48" OpenPaneLength="256" 
                   IsPaneOpen="True">

            <SplitView.Pane>
                <Grid Background="#CC000000">
                    <Grid.RowDefinitions>
                        <!--空出Button的高度-->
                        <RowDefinition Height="48" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <!--一級菜單-->
                    <ListView Name="NavMenuPrimaryListView" 
                              Grid.Row="1" VerticalAlignment="Top" 
                              SelectionMode="None" IsItemClickEnabled="True" 
                              ItemTemplate="{StaticResource DataTemplate}" 
                              ItemContainerStyle="{StaticResource NavMenuItemContainerStyle}"/>
                    <!--二級菜單-->
                    <ListView Name="NavMenuSecondaryListView" 
                              Grid.Row="2" VerticalAlignment="Bottom" 
                              SelectionMode="None" IsItemClickEnabled="True" 
                              ItemTemplate="{StaticResource DataTemplate}" 
                              ItemContainerStyle="{StaticResource NavMenuItemContainerStyle}" 
                              BorderBrush="{ThemeResource SystemControlBackgroundAccentBrush}" BorderThickness="0,1,0,0" />
                </Grid>
            </SplitView.Pane>

            <SplitView.Content>
                <Frame Name="RootFrame" />
            </SplitView.Content>

        </SplitView>
        
    </Grid>
</Page>

 

  主頁面的後臺代碼

using HamburgerDemo.Views;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

namespace HamburgerDemo
{
    public sealed partial class MainPage : Page
    {
        // 為不同的菜單創建不同的List類型
        private List<NavMenuItem> navMenuPrimaryItem = new List<NavMenuItem>(
            new[]
            {
                new NavMenuItem()
                {
                    FontFamily = new FontFamily("Segoe MDL2 Assets"),
                    Icon = "\xE10F",
                    Label = "頁面1",
                    Selected = Visibility.Visible,
                    DestPage = typeof(Page1)
                },

                new NavMenuItem()
                {
                    FontFamily = new FontFamily("Segoe MDL2 Assets"),
                    Icon = "\xE11A",
                    Label = "頁面2",
                    Selected = Visibility.Collapsed,
                    DestPage = typeof(Page1)
                },

                new NavMenuItem()
                {
                    FontFamily = new FontFamily("Segoe MDL2 Assets"),
                    Icon = "\xE121",
                    Label = "頁面3",
                    Selected = Visibility.Collapsed,
                    DestPage = typeof(Page1)
                },

                new NavMenuItem()
                {
                    FontFamily = new FontFamily("Segoe MDL2 Assets"),
                    Icon = "\xE122",
                    Label = "頁面4",
                    Selected = Visibility.Collapsed,
                    DestPage = typeof(Page1)
                }

            });

        private List<NavMenuItem> navMenuSecondaryItem = new List<NavMenuItem>(
            new[]
            {
                new NavMenuItem()
                {
                    FontFamily = new FontFamily("Segoe MDL2 Assets"),
                    Icon = "\xE713",
                    Label = "設置",
                    Selected = Visibility.Collapsed,
                    DestPage = typeof(Page1)
                }
            });

        public MainPage()
        {
            this.InitializeComponent();
            // 綁定導航菜單
            NavMenuPrimaryListView.ItemsSource = navMenuPrimaryItem;
            NavMenuSecondaryListView.ItemsSource = navMenuSecondaryItem;
            // SplitView 開關
            PaneOpenButton.Click += (sender, args) =>
            {
                RootSplitView.IsPaneOpen = !RootSplitView.IsPaneOpen;
            };
            // 導航事件
            NavMenuPrimaryListView.ItemClick += NavMenuListView_ItemClick;
            NavMenuSecondaryListView.ItemClick += NavMenuListView_ItemClick;
            // 預設頁
            RootFrame.SourcePageType = typeof(Page1);
        }

        private void NavMenuListView_ItemClick(object sender, ItemClickEventArgs e)
        {
            // 遍歷,將選中Rectangle隱藏
            foreach (var np in navMenuPrimaryItem)
            {
                np.Selected = Visibility.Collapsed;
            }
            foreach (var ns in navMenuSecondaryItem)
            {
                ns.Selected = Visibility.Collapsed;
            }

            NavMenuItem item = e.ClickedItem as NavMenuItem;
            // Rectangle顯示並導航
            item.Selected = Visibility.Visible;
            if (item.DestPage != null)
            {
                RootFrame.Navigate(item.DestPage);
            }

            RootSplitView.IsPaneOpen = false;
        }
    }
}

 

  運行效果圖如下


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!doctype html><html><head><meta charset="utf-8"><title>無標題文檔</title><style>body{ background:#000;}.upshop-view{ width:320px; height:499px; background ...
  • 上面的兩張圖片中,你能看出有什麼不同嗎? 右圖使用 html5 canvas api 中的 和 函數嵌入了一段文字。 道理很簡單, 函數返回一個 對象,該對象包含三個屬性: 是一個位元組數組,每 4 位元組表示圖片中一個像素,按照“ 紅、綠、藍、透明度”的順序依次排列, 表示圖片寬度, 圖片高度。 只要 ...
  • 關於“加入收藏”的代碼,很多人都不會重視,一般情況是隨便在網上搜一個代碼放在頁面里就草草了事了。可是都沒有做到主流瀏覽器的相容。下麵分享一段使用 jQuery 實現加入收藏夾的功能。 ...
  • [1]h [2]p [3]div [4]hr [5]pre [6]blockquote [7]address [8]其他 ...
  • 我們在做頁面佈局的時候,經常需要利用浮動來實現一些佈局效果,這樣帶來的後果就會導致父元素丟失寬度。今天我們就來說說‘找回‘寬度的方法。 而清除浮動後的效果應該是這樣的請看: 下麵就說說方法,方法其實有非常的多,下麵部分方法的截圖請大家參考 (1)父級div定義height。(2)結尾處加空div標簽 ...
  • 四、Others部分、技術類1、http狀態碼有哪些?分別代表是什麼意思?2、說說創建ajax的過程3、一個頁面從輸入 URL 到頁面載入顯示完成,這個過程中都發生了什麼?4、說說你對網站重構的理解?5、網頁驗證碼是幹嘛的,是為瞭解決什麼安全問題。6、請說出三種減少頁面載入時間的方法。7、你有用 ...
  • 搞PC項目,最頭疼的莫過於做IE6/7/8的相容性(很蛋疼的事)。而在如今移動端H5的興起中,面對形形色色的機型,各種各樣的品牌手機,導致我嗎們FE們要做各種手機適配問題、樣式相容問題等等(巨煩,找問題還不好找)。以下是在移動端項目之路上所遇到的各種問題: UC瀏覽器——css3的坑 最近在做一個移 ...
  • 在之前的博文《Android中使用ViewPager實現屏幕頁面切換和引導頁效果實現》和《Android中Fragment的兩種創建方式》以及《Android中Fragment與Activity之間的交互(兩種實現方式)》中我們介紹了ViewPager以及Fragment各自的使用場景以及不同的實現 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...