Windows 10 开发 – 自适应代码
Windows 10 开发 – 自适应代码
在本章中,我们将演示如何在 Windows 10 支持的不同设备上采用您的应用程序。我们已经了解了如何采用您的 UI 以及 UWP 应用程序中使用的所有技巧、技术和控件。
现在,我们将学习采用您的代码,因为
-
所有设备的应用程序代码都不相同。
-
所使用的 API,尤其是用于 Xbox 的 API,将无法用于移动设备。HoloLens 等也是如此。
自适应代码可以有条件地点亮您的应用程序并仅在特定设备系列和/或特定版本的平台/扩展 API 上运行时才执行代码。
编写代码
在 Windows 10 中,你可以使用 C++、C#、Visual Basic 或 JavaScript 在 Visual Studio 中实现 UWP 应用程序。
-
借助 C# 和 Visual Basic,您可以使用 XAML 进行 UI 设计。
-
使用 C++,您可以使用 DirectX 而不是使用 XAML。
-
对于 JavaScript,您可以将 HTML 用于表示层,这是一种跨平台的 Web 标准。
Windows 核心 API 以相同的方式在所有设备上运行,其中包含您的代码和 UI 所需的大部分功能。但是,对于为特定设备系列量身定制的代码和UI,您需要使用自适应代码和自适应UI。
调用目标设备系列未实现的 API –
用户界面很容易适应不同的屏幕,但不同的设备系列不仅有不同的屏幕尺寸,它还有很多。
-
例如,手机有一些硬件按钮,如返回和摄像头,这些按钮在其他设备(如 PC)上可能不可用。
-
默认情况下,核心 API 包含大部分功能,适用于所有设备,但可以通过引用 UWP 应用程序中的扩展 SDK 来使用特定于设备的功能,就像外部程序集一样。
要添加您的应用程序中需要的任何特定扩展 SDK,请按照以下步骤操作 –
-
右键单击References。
-
选择“添加引用…”。将打开以下对话框。
-
添加扩展就像添加项目引用一样简单。
-
现在您可以从列表中添加任何扩展 SDK,包括桌面扩展、物联网扩展和移动扩展等。
桌面和移动扩展是两种最常见的平台扩展 SDK。例如,移动扩展启用使用硬件相机按钮所需的 API。
您可以使用Windows.Foundation.Metadata.ApiInformation类方法检查设备功能,如果当前设备支持该类型,则该方法返回布尔输出。例如,您可以使您的 Windows 应用程序使用具有以下代码的相机按钮 –
bool isHardwareButtonsAPIPresent = Windows.Foundation.Metadata.ApiInformation. IsTypePresent("Windows.Phone.UI.Inpu t.HardwareButtons"); if (isHardwareButtonsAPIPresent) { Windows.Phone.UI.Input.HardwareButtons.CameraPressed += HardwareButtons_CameraPressed; }
只有在设备上启用了移动扩展 SDK 时,手机摄像头按钮代码才会执行。同样,您还可以使用IsEventPresent、IsMethodPresent、IsPropertyPresent而不是IsTypePresent来检查当前 API 版本中的任何特定事件、方法或属性,如下所示。
bool isHardwareButtons_CameraPressedAPIPresent = Windows.Foundation.Metadata.ApiInformation.IsEventPresent ("Windows.Phone.UI.Input.HardwareButtons", "CameraPressed");
UWP 中的 Win32 API
使用 C++/CX 编写的通用寡妇平台 (UWP) 应用程序或 Windows 运行时组件可以访问 Win32 API,它们现在也是 UWP 的一部分。所有 Windows 10 设备系列都可以通过将您的应用程序与Windowsapp.lib链接来实现 Win32 API 。
Windowsapp.lib是一个“伞形”库,为 UWP API 提供导出。链接到Windowsapp.lib将添加到您的应用程序对所有 Windows 10 设备系列中存在的dll 的依赖项。
让我们看一个简单的例子,其中应用程序同时针对桌面和手机。因此,当应用程序在桌面上运行时,不会显示状态栏,但在手机上运行相同的应用程序时,它会显示状态栏。
下面给出了添加不同控件的 XAML 代码。
<Page x:Class = "UWPAdoptiveCode.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "using:UWPAdoptiveCode" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d"> <Page.Background> <SolidColorBrush Color = "Green"/> </Page.Background> <Page.BottomAppBar> <CommandBar x:Name = "commandBar" > <AppBarButton Icon = "Accept" Label = "appbarbutton"/> <AppBarButton Icon = "Cancel" Label = "appbarbutton"/> </CommandBar> </Page.BottomAppBar> <Grid Background = "AliceBlue"> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState> <VisualState.StateTriggers> <local:DeviceFamilyTrigger DeviceFamily = "Desktop" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target = "StatusBarControls.Visibility" Value = "Collapsed"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <StackPanel HorizontalAlignment = "Left" Margin = "75,164,0,0" VerticalAlignment = "Top" > <RadioButton x:Name = "ShowAppBarRadioButton" Content = "Show AppBar" HorizontalAlignment = "Stretch" VerticalAlignment = "Stretch" IsChecked = "True" Checked = "RadioButton_Checked"/> <RadioButton x:Name = "ShowOpaqueAppBarRadioButton" Content = "Show Transparent AppBar" HorizontalAlignment = "Stretch" VerticalAlignment = "Stretch" Checked = "RadioButton_Checked"/> <RadioButton x:Name = "HideAppBarRadioButton" Content = "Hide AppBar" HorizontalAlignment = "Stretch" VerticalAlignment = "Stretch" Checked = "RadioButton_Checked"/> </StackPanel> <StackPanel x:Name = "StatusBarControls" Orientation = "Vertical" Margin = "75,350,0,0" Visibility = "Visible"> <CheckBox x:Name = "StatusBarBackgroundCheckBox" Content = "Set StatusBar Background" Checked = "StatusBarBackgroundCheckBox_Checked" Unchecked = "StatusBarBackgroundCheckBox_Unchecked"/> <CheckBox x:Name = "StatusBarHiddenCheckBox" Content = "Set StatusBar Hidden" Checked = "StatusBarHiddenCheckBox_Checked" Unchecked = "StatusBarHiddenCheckBox_Unchecked"/> </StackPanel> </Grid> </Page>
下面给出了不同事件的 C# 实现。
using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 namespace UWPAdoptiveCode { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { private Color? DefaultTitleBarButtonsBGColor; private Color? DefaultTitleBarBGColor; public MainPage() { this.InitializeComponent(); //Windows.UI.ViewManagement.ApplicationView.GetForCurrentView(). VisibleBoundsCh anged += MainPage_VisibleBoundsChanged; var viewTitleBar = Windows.UI.ViewManagement.ApplicationView. GetForCurrentView().TitleBar; DefaultTitleBarBGColor = viewTitleBar.BackgroundColor; DefaultTitleBarButtonsBGColor = viewTitleBar.ButtonBackgroundColor; } private void RadioButton_Checked(object sender, RoutedEventArgs e) { // Bottom AppBar shows on Desktop and Mobile if (ShowAppBarRadioButton != null) { if (ShowAppBarRadioButton.IsChecked.HasValue && (ShowAppBarRadioButton.IsChecked.Value == true)) { commandBar.Visibility = Windows.UI.Xaml.Visibility.Visible; commandBar.Opacity = 1; } else { commandBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed; } } if (ShowOpaqueAppBarRadioButton != null) { if (ShowOpaqueAppBarRadioButton.IsChecked.HasValue && (ShowOpaqueAppBarRadioButton.IsChecked.Value == true)){ commandBar.Visibility = Windows.UI.Xaml.Visibility.Visible; commandBar.Background.Opacity = 0; } else{ commandBar.Background.Opacity = 1; } } } private void StatusBarHiddenCheckBox_Checked(object sender, RoutedEventArgs e){ // StatusBar is Mobile only if (Windows.Foundation.Metadata.ApiInformation. IsTypePresent("Windows.UI.ViewManag ement.StatusBar")){ var ignore = Windows.UI.ViewManagement.StatusBar.GetForCurrentView().HideAsync(); } } private void StatusBarHiddenCheckBox_Unchecked(object sender, RoutedEventArgs e){ // StatusBar is Mobile only if (Windows.Foundation.Metadata.ApiInformation. IsTypePresent("Windows.UI.ViewManag ement.StatusBar")){ var ignore = Windows.UI.ViewManagement.StatusBar.GetForCurrentView().ShowAsync(); } } private void StatusBarBackgroundCheckBox_Checked(object sender, RoutedEventArgs e){ // StatusBar is Mobile only if (Windows.Foundation.Metadata.ApiInformation. IsTypePresent("Windows.UI.ViewManag ement.StatusBar")){ Windows.UI.ViewManagement.StatusBar.GetForCurrentView(). BackgroundColor = Windows.UI.Colors.Blue; Windows.UI.ViewManagement.StatusBar.GetForCurrentView(). BackgroundOpacity = 1; } } private void StatusBarBackgroundCheckBox_Unchecked(object sender, RoutedEventArgs e){ // StatusBar is Mobile only if (Windows.Foundation.Metadata.ApiInformation. IsTypePresent("Windows.UI.ViewManag ement.StatusBar")){ Windows.UI.ViewManagement.StatusBar.GetForCurrentView(). BackgroundOpacity = 0; } } } public class DeviceFamilyTrigger : StateTriggerBase{ //private variables private string _deviceFamily; //Public property public string DeviceFamily { get { return _deviceFamily; } set{ _deviceFamily = value; var qualifiers = Windows.ApplicationModel.Resources.Core.ResourceContext. GetForCurrentView().Qua lifierValues; if (qualifiers.ContainsKey("DeviceFamily")) SetActive(qualifiers["DeviceFamily"] == _deviceFamily); else SetActive(false); } } } }
当上面给出的代码在移动设备上编译和执行时,您将看到以下窗口。
您可以使用复选框更改状态栏的背景颜色,如图所示。
您还可以隐藏状态栏。
现在,当您在桌面设备上运行相同的应用程序时,您将看到以下窗口,其中状态栏和特定于状态栏的复选框不可见。