张高兴的 UWP 开发笔记:汉堡菜单进阶
不同于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,解决方案结构如下。(GitHub https://github.com/ZhangGaoxing/uwp-demo/tree/master/HamburgerDemo)

先创建一个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="" 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;
}
}
}
运行效果图如下

张高兴的 UWP 开发笔记:汉堡菜单进阶的更多相关文章
- 张高兴的 UWP 开发笔记:用 Thumb 控件仿制一个可拖动 Button
在 WPF 上可用的控件拖动方法在 UWP 上大多没用,那干脆用 Thumb 仿制一个吧. 关于 Thumb 控件的教程也不多,毕竟在 WPF 控件拖动有很多种方法, Thumb 就显得很鸡肋了.下面 ...
- 张高兴的 UWP 开发笔记:横向 ListView
ListView 默认的排列方向是纵向 ( Orientation="Vertical" ) ,但如果我们需要横向显示的 ListView 怎么办? Blend for Visua ...
- 张高兴的 UWP 开发笔记:应用内启动应用 (UWP Launch UWP)
需求:在 A 应用内启动 B 应用,如果 B 应用未安装则跳转应用商店搜索. 启动方式使用 Uri 启动,本文使用尽可能简单,并且能拿来直接用的代码.不涉及启动后的应用数据交互,如需深入了解,请戳 M ...
- 张高兴的 UWP 开发笔记:手机状态栏 StatusBar
UWP 有关应用标题栏 TitleBar 的文章比较多,但介绍 StatusBar 的却没几篇,在这里随便写写.状态栏 StatusBar 用法比较简单,花点心思稍微设计一下,对应用会是个很好的点缀. ...
- 张高兴的 UWP 开发笔记:定制 ContentDialog 样式
我需要一个背景透明的 ContentDialog,像下图一样.如何定制?写了一个简单的示例(https://github.com/ZhangGaoxing/uwp-demo/tree/master/C ...
- 张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )
所谓 UWP 样式的汉堡菜单,我曾在"张高兴的 UWP 开发笔记:汉堡菜单进阶"里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色 ...
- UWP开发笔记——嵌套式页面的实现
绪论 UWP开发中,Page是最常用的Control之一,通常情况下,在开发的application中,每一个页面就是一个Page.有时候,为了开发整合度更高,UI表现更为一致的UI,开发者需要把UI ...
- 安卓开发笔记——Menu菜单组件(选项菜单,上下文菜单,子菜单)
菜单是用户界面中最常见的元素之一,使用非常频繁,在Android中,菜单被分为如下三种,选项菜单(OptionsMenu).上下文菜单(ContextMenu)和子菜单(SubMenu). 菜单的实现 ...
- uwp汉堡菜单的实现
---恢复内容开始--- 现在uwp上面的汉堡菜单(就是那个三道杠,点击之后会出现菜单)使用的越来越普遍,比如微软自己家的Cortana.现在我使用的实现方法是使用SplitView实现.首先Spli ...
随机推荐
- ExtJS 4.2 评分组件
上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...
- 【疯狂造轮子-iOS】JSON转Model系列之一
[疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...
- ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面
前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...
- React使用antd Table生成层级多选组件
一.需求 用户对不同的应用需要有不同的权限,用户一般和角色关联在一起,新建角色的时候会选择该角色对应的应用,然后对应用分配权限.于是写了一种实现的方式.首先应用是一个二级树,一级表示的是应用分组,二级 ...
- MVC如何使用开源分页插件shenniu.pager.js
最近比较忙,前期忙公司手机端接口项目,各种开发+调试+发布现在几乎上线无问题了:虽然公司项目忙不过在期间抽空做了两件个人觉得有意义的事情,一者使用aspnetcore开发了个人线上项目(要说线上其实只 ...
- psoc学习
第一是:项目的路径需要放在Documents and Settings\,也就是默认的文件夹的地方,不然会报错错误范例为:Question:CY8CKIT-023 kit example projec ...
- jQuery个性化图片轮播效果
jQuery个性化图片轮播效果 购物产品展示:图片轮播器<效果如下所示> 思路说明: 每隔一段时间,实现图片的自动切换及选项卡选中效果,鼠标划入图片动画停止,划出或离开动画开始 两个区域: ...
- SuperMap-iServer-单点登录功能验证(CAS)
SuperMap-iServer-单点登录功能验证(CAS) 1.测试目的: 验证SuperMap-iServer使用CAS单点登录的功能是否正常. 2.测试环境: SuperMap-iServer8 ...
- ASP.NET Core MVC 中的 [Controller] 和 [NonController]
前言 我们知道,在 MVC 应用程序中,有一部分约定的内容.其中关于 Controller 的约定是这样的. 每个 Controller 类的名字以 Controller 结尾,并且放置在 Contr ...
- Android(2)—Mono For Android App版本自动更新
0.前言 公司Android查询的项目已经开始,整体采用Java后台+App前台来实现,由于项目小,App这块就我一个人开发,首先需要研究的是:Android版本的更新升级问题:本人经过近一周的学习整 ...