博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[UWP]占领标题栏
阅读量:5044 次
发布时间:2019-06-12

本文共 7420 字,大约阅读时间需要 24 分钟。

1. 前言

每一个有理想的UWP应用都会打标题栏的主意,尤其当微软提供 这个功能后,大部分Windows 10的原生应用都不乖了,纷纷占领了标题栏的一亩三分地。这篇博客将介绍在UWP中如何自定义标题栏。

2.示例代码

UWP的限制很多,标题栏的自定义几乎全部内容集中在 里面。但只参考这篇文章做起来还不够顺手,我参考了微软开源的计算器应用中的 写了一个示例应用,可以在 查看它的源码。我也把TitleBar实际应用到了我的 应用里面了。

3. 简单的颜色自定义

如果只想简单地自定义标题栏的颜色可以通过,ApplicationViewTitleBar表示应用程序的标题栏,它提供了一些颜色属性用于控制标题栏的颜色,示例代码如下:

// using Windows.UI.ViewManagement;var titleBar = ApplicationView.GetForCurrentView().TitleBar;// Set active window colorstitleBar.ForegroundColor = Windows.UI.Colors.White;titleBar.BackgroundColor = Windows.UI.Colors.Green;titleBar.ButtonForegroundColor = Windows.UI.Colors.White;titleBar.ButtonBackgroundColor = Windows.UI.Colors.SeaGreen;titleBar.ButtonHoverForegroundColor = Windows.UI.Colors.White;titleBar.ButtonHoverBackgroundColor = Windows.UI.Colors.DarkSeaGreen;titleBar.ButtonPressedForegroundColor = Windows.UI.Colors.Gray;titleBar.ButtonPressedBackgroundColor = Windows.UI.Colors.LightGreen;// Set inactive window colorstitleBar.InactiveForegroundColor = Windows.UI.Colors.Gray;titleBar.InactiveBackgroundColor = Windows.UI.Colors.SeaGreen;titleBar.ButtonInactiveForegroundColor = Windows.UI.Colors.Gray;titleBar.ButtonInactiveBackgroundColor = Windows.UI.Colors.SeaGreen;

有几点需要注意:

  • 悬停和按下状态的Background定义对关闭按钮无效
  • Foreground不能设置透明

4. 将内容扩展到标题栏

若要隐藏默认标题栏并将你的内容扩展到标题栏区域中,请将 属性设置为 true。允许应用定义在应用窗口中显示的自定义标题栏。示例代码如下:

// using Windows.ApplicationModel.Core;// Hide default title bar.var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;coreTitleBar.ExtendViewIntoTitleBar = true;

5. 将内容扩展到标题栏时自定义标题按钮颜色

将内容扩展到标题栏,标题按钮的颜色就变复杂了。因为应用内容的颜色可能和按钮的颜色冲突。这种情况下有几种方案,其中最简单的一种方案是写死为一个不会冲突的颜色,但切换主题时可能会让这些颜色出问题。计算器应用中订阅的ColorValuesChanged事件,动态地根据ThemeResources的值改变标题栏颜色,并且更进一步地考虑到使用高对比度主题的情况,所以订阅了的HighContrastChanged事件:

if (_accessibilitySettings.HighContrast){    // Reset to use default colors.    applicationTitleBar.ButtonBackgroundColor = null;    applicationTitleBar.ButtonForegroundColor = null;    applicationTitleBar.ButtonInactiveBackgroundColor = null;    applicationTitleBar.ButtonInactiveForegroundColor = null;    applicationTitleBar.ButtonHoverBackgroundColor = null;    applicationTitleBar.ButtonHoverForegroundColor = null;    applicationTitleBar.ButtonPressedBackgroundColor = null;    applicationTitleBar.ButtonPressedForegroundColor = null;}else{    Color bgColor = Colors.Transparent;    Color fgColor = ((SolidColorBrush)Application.Current.Resources["SystemControlPageTextBaseHighBrush"]).Color;    Color inactivefgColor = ((SolidColorBrush)Application.Current.Resources["SystemControlForegroundChromeDisabledLowBrush"]).Color;    Color hoverbgColor = ((SolidColorBrush)Application.Current.Resources["SystemControlBackgroundListLowBrush"]).Color;    Color hoverfgColor = ((SolidColorBrush)Application.Current.Resources["SystemControlForegroundBaseHighBrush"]).Color;    Color pressedbgColor = ((SolidColorBrush)Application.Current.Resources["SystemControlBackgroundListMediumBrush"]).Color;    Color pressedfgColor = ((SolidColorBrush)Application.Current.Resources["SystemControlForegroundBaseHighBrush"]).Color;    applicationTitleBar.ButtonBackgroundColor = bgColor;    applicationTitleBar.ButtonForegroundColor = fgColor;    applicationTitleBar.ButtonInactiveBackgroundColor = bgColor;    applicationTitleBar.ButtonInactiveForegroundColor = inactivefgColor;    applicationTitleBar.ButtonHoverBackgroundColor = hoverbgColor;    applicationTitleBar.ButtonHoverForegroundColor = hoverfgColor;    applicationTitleBar.ButtonPressedBackgroundColor = pressedbgColor;    applicationTitleBar.ButtonPressedForegroundColor = pressedfgColor;}

这段代码中,当使用高对比度主题时将标题栏的按钮颜色还原成默认值,否则设置成ThemeResource中对应的颜色,运行效果如下:

38937-20190903220748811-861096530.gif

但现在的UWP应用常常在Dark和Light主题之间反复横跳,而Application.Current.Resources只能拿到程序加载时的ThemeResource的值,所以这段代码在应用内的主题切换后无效。我暂时不清楚怎么在代码里拿到最新的ThemeResource,为解决这个问题只好让TitleBar自己在XAML中获取当前的ThemeResource,代码如下:

Color fgColor = ((SolidColorBrush)Resources["ButtonForegroundColor"]).Color;Color inactivefgColor = ((SolidColorBrush)Resources["ButtonInactiveForegroundBrush"]).Color;Color hoverbgColor = ((SolidColorBrush)Resources["ButtonHoverBackgroundBrush"]).Color;Color hoverfgColor = ((SolidColorBrush)Resources["ButtonHoverForegroundBrush"]).Color;Color pressedbgColor = ((SolidColorBrush)Resources["ButtonPressedBackgroundBrush"]).Color;Color pressedfgColor = ((SolidColorBrush)Resources["ButtonPressedForegroundBrush"]).Color;

38937-20190903225509008-574502814.gif

6. 可拖动区域

都将内容扩展到标题栏了,肯定是想在标题栏上放置自己需要的UI元素,默认情况下标题栏的范围为拖动、点击等Windows的窗体行为保留,在这个范围的自定义UI内容没办法获取鼠标点击。 为了让自定义的UI内容获取鼠标,可以用方法指定某一元素能用于窗体的拖动和点击。

Window.Current.SetTitleBar(BackgroundElement);

上面的代码指定TitlaBar中的BackgroundElement元素为可拖动区域,而下面的StackPanel则用于放置交互内容,例如标题或后退按钮。这个StackPanel必须比BackgroundElement具有较高的Z顺序才能接收到用户的鼠标输入。

7. 标题的系统保留区域

标题栏的右边有188像素的系统保留区域,用于系统标题按钮(“后退”、“最小化”、“最大化”、“关闭”)。其实这几个按钮也就占用了141像素的控件,还有一小块空间是默认的可拖动区域,这小块空间确保了无论怎么设置都总有一个用户可拖动的区域。

38937-20190903231301785-139487849.png

上面说的188像素是100%缩放的情况,通过上面的截图可以看到实际上可能不一样,通常来说会在窗体加载时,或者订阅事件,然后通过CoreApplicationViewTitleBar获取具体的值。

_coreTitleBar.LayoutMetricsChanged += OnLayoutMetricsChanged;private void OnLayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args){    LayoutRoot.Height = _coreTitleBar.Height;    SetTitleBarPadding();}private void SetTitleBarPadding(){    double leftAddition = 0;    double rightAddition = 0;    if (FlowDirection == FlowDirection.LeftToRight)    {        leftAddition = _coreTitleBar.SystemOverlayLeftInset;        rightAddition = _coreTitleBar.SystemOverlayRightInset;    }    else    {        leftAddition = _coreTitleBar.SystemOverlayRightInset;        rightAddition = _coreTitleBar.SystemOverlayLeftInset;    }    LayoutRoot.Padding = new Thickness(leftAddition, 0, rightAddition, 0);}

8. 可交互区域的内容

上面的StackPanel是可交互区域,详细的内容如下:

其中AppName用于显示标题栏,ItemsPanel用于放其它按钮。TitleBar里定义了Buttons属性,调用TitleBar可以通过Buttons属性指定按钮(这部分代码我凌晨两点写的,写得十分敷衍,但写完又懒得改了)。

public ObservableCollection

38937-20190903231459886-64622227.png

按钮的样式来自NavigationBackButtonNormalStyle并稍作修改,大致上做到和标准的标题栏按钮一样。

9. 非激活状态的标题栏颜色

当窗体处于非激活状态应该让按钮和标题都变灰,可以订阅Window的事件,在非激活状态时改变颜色:

Window.Current.Activated += OnWindowActivated;private void OnWindowActivated(Object sender, WindowActivatedEventArgs e){    VisualStateManager.GoToState(        this, e.WindowActivationState == CoreWindowActivationState.Deactivated ? WindowNotFocused.Name : WindowFocused.Name, false);}

38937-20190903231709232-1123764478.gif

10. 全屏和平板模式

当应用在全屏或平板模式下运行时,系统将隐藏标题栏和标题控制按钮。 但是,用户可以调用标题栏,以使其以覆盖形式显示在应用的 UI 顶部。 你可以处理隐藏或调用标题栏时将通知的 事件,并根据需要显示或隐藏你的自定义标题栏内容。

LayoutRoot.Visibility = _coreTitleBar.IsVisible ? Visibility.Visible : Visibility.Collapsed;

这部分比较难截图就不搞了,想看效果可以试玩我的。

11.结语

就这样,令人头痛的自定义标题栏处理完了。还好微软开源了它的计算器里正好有我需要的代码,抄了个爽。有一些处理得不好,如果错误请指正。

12.参考

13. 源码

转载于:https://www.cnblogs.com/dino623/p/uwp-title-bar.html

你可能感兴趣的文章
CentOS 安装 debuginfo-install
查看>>
CSS布局:让页底内容永远固定在底部
查看>>
RichEdit
查看>>
路由器和交换机的区别
查看>>
Coursera台大机器学习课程笔记14 -- Validation
查看>>
易之 - 我是个算命先生(2014年3月23日)
查看>>
C# :面向对象
查看>>
JavaScript中的正则表达式
查看>>
【公众号系列】SAP HANA 平台的优势
查看>>
VMware+Fedora20+secureCRT7.0配置心得
查看>>
20172328《程序设计与数据结构》第五周学习总结
查看>>
memcached完全剖析–1. memcached的基础(转)
查看>>
Eigen vs Numpy时间对比
查看>>
Java学习笔记(七)——获取类中方法的信息,java的LinkedList
查看>>
js修改伪类元素样式
查看>>
SQL常用语句
查看>>
多线程之ReadWriteLock模拟缓存(九)
查看>>
工作碰到的非代码问题总结
查看>>
构造函数与析构函数
查看>>
GetCursorPos
查看>>