UWP 扩展/自定义标题栏的方法,一些概念和一些注意事项

简介: 原文 UWP 扩展/自定义标题栏的方法,一些概念和一些注意事项 在 Windows 10 的前几个版本中将页面内容扩展到标题栏上还算简单,主要是没什么坑。直到一些新控件的引入和一些外观设计趋势变化之后,扩展标题栏开始出现一些坑了。

原文 UWP 扩展/自定义标题栏的方法,一些概念和一些注意事项

在 Windows 10 的前几个版本中将页面内容扩展到标题栏上还算简单,主要是没什么坑。直到一些新控件的引入和一些外观设计趋势变化之后,扩展标题栏开始出现一些坑了。

本文将重温 UWP 自定义标题栏或者扩展标题栏的方法,但更重要的是解决一些坑。


扩展/自定义标题栏

要扩展标题栏,只需要拿到 CoreApplicationView 的实例,然后设置 TitleBar 的 ExtendViewIntoTitleBar 属性为 true 即可。

var applicationView = CoreApplication.GetCurrentView(); applicationView.TitleBar.ExtendViewIntoTitleBar = true; 

要自定义标题栏,只需要拿到 ApplicationView 的实例,然后设置 TitleBar 里各种属性接口。

var titleBar = ApplicationView.GetForCurrentView().TitleBar; titleBar.BackgroundColor = Colors.Khaki; titleBar.ButtonBackgroundColor = Colors.Transparent; 

一些概念

那么问题来了,为什么前者需要拿到 CoreApplicationView 的实例,后者需要拿到 ApplicationView 的实例?它们到底是什么区别?

我在 CoreApplication/Application、CoreWindow/Window 之间的区别 一文中提到过 CoreApplicationCoreWindow 和 CoreDispatcher 之间的关系。继续借用那篇文章中的图:

UWP 创建应用视图

其中,Window 是对 CoreWindow 的封装,提供了更多与 XAML 相关的功能。这里的 ApplicationView 也是这样,是对 CoreApplication 的封装,提供了 XAML 相关的功能。

那篇文章中详细描述了这几个概念之间的关系和区别。考虑到阅读的一致性,我摘抄过来:

具体来说,CoreWindow 是与操作系统、与整个应用打交道的类型,提供了诸如窗口的尺寸、位置、输入状态等设置或调用;Window 是与应用内 UI 打交道的类型,比如可以设置窗口内显示的 UI,设置内部哪个控件属于标题栏,获取此窗口内的 Compositor。与之对应的,CoreApplicationView 是应用与操作系统交互,与窗口消息循环机制协同工作的类型,包含窗口客户区和非客户区设置;ApplicationView 也是与应用内 UI 打交道的类型,它可以使用 XAML 相关的类型对应用程序视图进行更方便的设置。

总结起来,CoreWindow 和 CoreApplicationView 提供更加核心的操作系统或应用底层功能,而 Window 和 ApplicationView 对前者进行了封装,使得我们能够使用 Windows.UI.Xaml 命名空间下的类型对窗口和应用视图进行控制。

于是,我们便能够理解为什么扩展标题栏和设置标题栏颜色会使用到两个不一样的类型了。

ExtendViewIntoTitleBar 是改变了窗口的客户区(Client Area)和非客户区(Non-client Area)组成,这是传统 Win32 编程中的概念,是更接近操作系统底层的概念。BackgroundColor 和 ButtonBackgroundColor 这里需要用到 Windows.UI.Xaml 命名空间中的颜色,而 CoreApplicationView 太底层,无法使用 XAML 颜色。

一些坑

控件在标题栏区域无法交互

想必当你扩展到标题栏后,在标题栏区域增加一些按钮的时候,肯定会遇到下面的情况:

控件的一半无法交互
▲ 按钮在标题栏区域的一半无法交互

这显然是无法接受的。

然而,当我们将一个 XAML 控件指定为标题栏之后,就只会是那个控件所在的区域响应标题栏操作,其他地方就会恢复正常。

// TitleBar 是我在 XAML 中写的一个 x:Name="TitleBar" 的控件。
Window.Current.SetTitleBar(TitleBar); 

设置了一个标题栏
▲ 按钮在标题栏区域现在可以交互了

特别说明一下,SetTitleBar 传入的是 UIElement 类型的实例,也就是说这也是 XAML 交互的一部分。我们需要使用 Window 的实例,而不是 CoreWindow 的实例。

更高的标题栏,或者被遮挡

如果被指定为标题栏的控件更大,超出标题栏区域了,它还会成为标题栏吗?如果被其他控件遮挡了,它还会响应标题栏事件吗?

实际看来,无论它多大,都能响应标题栏事件;但被遮挡的部分就真的被遮挡了,没有标题栏响应。

更高的标题栏,或者被遮挡
▲ 更高的标题栏,或者被遮挡

事实上,指定为标题栏的控件可以在界面的任何地方,不需要一定在顶部。只不过,绝大多数不作死的应用都不会这样设置吧!

在什么时机调用?

扩展标题栏用的是 CoreApplicationView,自定义标题栏颜色用的是 ApplicationView,将控件指定为标题栏用的是 Window。如果我们的应用只有一个视图,其实我们随便找一个初始化的地方调用就好了。但如果我们的应用有多个视图,那么给非主要视图调用的时候就需要在其初始化之后了。阅读 理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图) 了解如何编写多个视图的 UWP 应用,了解非主要视图的初始化时机。

当然,如果你比较极客,从 Main 函数开始写 UWP 应用,就像我在 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序 一文中做的一样,那么你也需要等到初始化完毕之后才能调用(至少是 SetWindow 之后了)。

适配移动设备

移动设备上并不是标题栏,而是状态了和虚拟按键。关于扩展视图到这些区域,可以阅读 win10 uwp 标题栏 - 林德熙


参考资料

本文会经常更新,请阅读原文: https://walterlv.com/post/tips-for-customize-uwp-title-bar.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

目录
相关文章
|
3月前
|
前端开发 PHP
ThinkPHP6布局的方式之模板布局,全局配置方式,模板标签方式,动态方法布局
本文介绍了ThinkPHP6中实现模板布局的三种方式:全局配置方式、模板标签方式和动态方法布局,并通过示例代码展示了如何在项目中应用这些布局方式。
ThinkPHP6布局的方式之模板布局,全局配置方式,模板标签方式,动态方法布局
|
自然语言处理 编译器 C#
【WPF】实现动态切换语言(国际化)以及动态换肤功能
以下内容,手把手从搭建到最终实现,完成多语言切换以及换装功能。
467 0
【WPF】实现动态切换语言(国际化)以及动态换肤功能
WPF界面无法正常显示(资源引用,如转换器),但程序正常运行
WPF界面无法正常显示(资源引用,如转换器),但程序正常运行
WPF界面无法正常显示(资源引用,如转换器),但程序正常运行
|
C#
WPF整理-为控件添加自定义附加属性
原文:WPF整理-为控件添加自定义附加属性 附加属性,大家都不陌生,最常见的是Canvas.Left/Canvas.Top,类似的也有Grid.Row/Grid.Column等附加属性。举个最常见的例子 需要说明的是并不是所有的附加属性都是元素放进去后才会有附加效果,上面的例子只是刚好是这种错觉的巧合情况,Grid.Row也属于这种巧合。
2132 0
WPF整理-为控件添加自定义附加属性
MFC怎么用代码改变CComboBox的下拉方式?
MFC怎么用代码改变CComboBox的下拉方式?
171 0
|
XML C# 数据格式
[UWP]为附加属性和依赖属性自定义代码段(兼容UWP和WPF)
原文:[UWP]为附加属性和依赖属性自定义代码段(兼容UWP和WPF) 1. 前言 之前介绍过依赖属性和附加属性的代码段,这两个代码段我用了很多年,一直都帮了我很多。不过这两个代码段我也多年没修改过,Resharper老是提示我生成的代码可以修改,它这么有诚意,这次就只好从了它,顺便简单介绍下怎么自定义代码段。
763 0
|
C# 前端开发
WPF Adorner+附加属性 实现控件友好提示
原文:WPF Adorner+附加属性 实现控件友好提示 标题太空泛,直接上图   无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做? 这里介绍一种稍微简单一些的方法,利用附加属性和Adorner来完成。
1005 0
|
C# 前端开发 Windows
在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
原文:在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象 这是我辅导的一个项目开发中的例子,他们是用WPF做界面开发,在学习了如何使用MVVM来实现界面与逻辑的分离,并且很好的数据更新之后,有一个疑问就是,这种双向的数据更新确实很不错,但如果我们希望用户可以撤销修改怎么办呢?其实这个功能,很早就有,甚至在原先的Windows Forms里面也可以实现。
972 0
|
Windows 缓存 异构计算
背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性
原文:背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性 [源码下载] 背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIE...
1057 0
|
Windows C#
背水一战 Windows 10 (78) - 自定义控件: 基础知识, 依赖属性, 附加属性
原文:背水一战 Windows 10 (78) - 自定义控件: 基础知识, 依赖属性, 附加属性 [源码下载] 背水一战 Windows 10 (78) - 自定义控件: 基础知识, 依赖属性, 附加属性 作者:webabcd介绍背水一战 Windows 10 之 控件(自定义控件) 自定...
1254 0

热门文章

最新文章