Viewbox在UWP开发中的应用

原文:Viewbox在UWP开发中的应用

Windows 8.1 与Windows Phone 8.1的UAP应用,终于在Windows 10上统一到了UWP之下。原来3个不同的project也变为一个。没有了2套xaml页面,我们需要用同一个页面适应所有的设备。更麻烦的是在Desktop设备上,我们的应用窗口是可以随意拖动大小的。这对我们的UI布局提出了更高的要求。当然我们也有了新的工具来应对:

VisualState中增加了StateTriggers,通过不同的条件触发Trigger并自动切换到对应的VisualState,还能加入自己定义触发条件的Trigger。

新增了RelativePanel控件,可以让其中的元素使用相对位置布局来适应不同的设备和窗口大小。

另一方面微软官方也发布了一些指导建议,比如Responsive design 101 for Universal Windows Platform (UWP) apps , UI basics for Universal Windows Platform (UWP) apps, Plan your Universal Windows Platform (UWP) app 等一系列文章。这对我们也很有启发。

然而这些都没有具体提到对于窗口大小拖动情况下的处理,下面就来分享一下我们在尝试开发UWP应用的过程中对这种情况的一些思考。

总体布局

我们的应用,总体上是非常简单地采用了UI basics for Universal Windows Platform (UWP) apps 中 图1和图2 的布局,有着始终显示的顶栏和底栏,中间则是内容显示区域。

如果沿用UAP的设计,我们可能会为顶栏和底栏设计一个固定高度,让中间的内容区域可以随屏幕大小来变化。然而在UWP中,我们的应用窗口可以在最小500 X 320,到全屏之间自由变化。如果仍然采用固定高度,那在窗口变小的情况下,内容区域就会被顶栏和底栏挤压,这并不是我们希望的。所以我们在全局的布局上采用了按比例分配的策略:

<Grid.RowDefinitions>

<RowDefinition x:Name="rd_1" Height="*" ></RowDefinition>

<RowDefinition x:Name="rd_2" Height="8*"></RowDefinition>

<RowDefinition Height="60*"></RowDefinition>

<RowDefinition x:Name="rd_4" Height="8*" ></RowDefinition>

<RowDefinition x:Name="rd_5" Height="*" ></RowDefinition>

</Grid.RowDefinitions>

这样一来在不同的窗口大小和设备的情况下都可以有所兼顾。

但这又带来新的问题:我们顶栏和底栏中的文字,图片大多是固定大小的。怎样才能让它们随屏幕和设备自动适应呢?用新的StateTriggers固然可以,但对于每个固定大小的控件,都要指定它们在不同VisualState下的新大小,有些麻烦。而且我们的布局并没有很大的变化,没有一定使用StateTriggers必要。所以这里我们想到了Viewbox 控件。Viewbox 是一个可以将其中内容缩放到自身大小的容器。我们在按比例划分的Grid中放入Viewbox ,再把顶栏和底栏放到Viewbox 中,这样他们就可以在不同窗口大小和设备上都保持统一的比例了:

<Viewbox x:Name="vbNav" Grid.Row="1" HorizontalAlignment="Left" Visibility="Visible">

<Grid Margin="50,0" >

<Image Source="{StaticResource mainPageMenuLeftImg}" Stretch="Uniform" HorizontalAlignment="Left" Height="160"

Margin="-20,0,0,0" VerticalAlignment="Center" Canvas.ZIndex="100"></Image>

<ListView x:Name="lvNav" SelectionMode="Single" Height="160" Canvas.ZIndex="99"

SelectionChanged="lvNav_SelectionChanged" HorizontalAlignment="Left"

VerticalAlignment="Center" ScrollViewer.HorizontalScrollMode="Enabled"

Background="#FFF6EBA1" ItemContainerStyle="{StaticResource ContextControlItemContainerStyle}">

<ListView.ItemsPanel>

<ItemsPanelTemplate>

<VirtualizingStackPanel Orientation="Horizontal" Margin="0" VerticalAlignment="Center"></VirtualizingStackPanel>

</ItemsPanelTemplate>

</ListView.ItemsPanel>

</ListView>

<Image Source="{StaticResource mainPageMenuRightImg}" Stretch="Uniform" HorizontalAlignment="Right" Height="160"

Margin="0,0,-20,0" VerticalAlignment="Center" Canvas.ZIndex="100"></Image>

</Grid>

</Viewbox>

这里的image和listview都是固定大小的,使用了viewbox以后就可以始终保持只占屏幕一定比例,而不会在小屏幕上超出Grid而在大屏幕上显得比较小了。

内容布局

我们的页面内容有2种,一种是内容列表,一种则是包括编辑和预览的界面。

对于内容列表,我们使用了Responsive design 101 for Universal Windows Platform (UWP) apps中的resize策略。

主要是一个横向滚动的GridView,在屏幕足够高的情况下显示3行或4行内容,较小的情况下则显示2行。然而这个较小的情况实际上覆盖了比较大的范围,如果仍然使用固定大小的列表元素控件则会遇到和顶栏和底栏类似的问题。所以我们又一次使用了viewbox: 将内容区域放一个Grid在最外层,再把包含GridView的viewbox放在其中。响应最外层的Grid的sizechange事件,改变GridView的长宽比例以适应显示区域。

Xaml:

<Grid x:Name="grid_content" SizeChanged="gridRoot_SizeChanged" Grid.Row="2">

<Viewbox>

<GridView x:Name="gv_Content" ItemContainerStyle="{StaticResource contentTemplateStyle}"

SelectionMode="Single" IsSynchronizedWithCurrentItem="{x:Null}"

SelectionChanged="gvContent_SelectionChanged" IsItemClickEnabled="True"

VerticalAlignment="Stretch" HorizontalAlignment="Stretch"

Width="630"

Height="774"

ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.HorizontalScrollBarVisibility="Visible"

Margin="20">

<GridView.ItemsPanel>

<ItemsPanelTemplate>

<WrapGrid Orientation="Vertical" Margin="0" MaximumRowsOrColumns="4" VerticalAlignment="Top"></WrapGrid>

</ItemsPanelTemplate>

</GridView.ItemsPanel>

</GridView>

</Viewbox>

</Grid>

CS:

private void gridRoot_SizeChanged(object sender, SizeChangedEventArgs e)

{

try

{

Grid thisGrid = sender as Grid;

if (thisGrid.ActualHeight >=480 && thisGrid.ActualHeight <=720)

{

this.gv_Content.Height = 784 * 1.5; //改变高度,放3个列表元素

}

else if (thisGrid.ActualHeight >720)

{

this.gv_Content.Height = 784 * 2; //改变高度,放4个列表元素

}

     else

{

this. gv_Content.Height = 784; //改变高度,放2个列表元素

}

this. gv_Content.Width = thisGrid.ActualWidth / (thisGrid.ActualHeight) * this. gv_Content.Height; //调整宽度,适应显示区域比例

}

catch (Exception ex)

{

Debug.WriteLine(ex.Source + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);

}

}

而包含编辑和预览的界面,我们则采取了在屏幕宽度较小的时候将预览界面隐藏,让界面可以在编辑和预览之间切换的策略。

小结

以上就是我们面对UWP在UI布局方面新特性的一部分心得,希望能抛砖引玉,吸引更多的小伙伴加入到UWP的开发中来。

时间: 2024-08-02 16:12:35

Viewbox在UWP开发中的应用的相关文章

Win10 UWP开发中的重复性静态UI绘制小技巧 2

原文:Win10 UWP开发中的重复性静态UI绘制小技巧 2 小技巧1 地址:http://www.cnblogs.com/ms-uap/p/4641419.html 介绍 我们在上一篇博文中展示了通过Shape.Stroke族属性实现静态重复性UI绘制,使得UWP界面的实现变得稍微灵活一些了. 但这一技巧还是有不少局限的,毕竟折腾StrokeDashArray属性看上去并不是那么直观和适用(还存在用扇形欺骗观众这样的"问题"啦). 这一篇博文我们将为大家介绍一种更为适用,同时也更为灵

Win10 UWP开发中的重复性静态UI绘制小技巧 1

原文:Win10 UWP开发中的重复性静态UI绘制小技巧 1 介绍 在Windows 10 UWP界面实现的过程中,有时会遇到一些重复性的.静态的界面设计.比如:画许多等距的线条,画一圈时钟型的刻度线,同特别的策略排布元素,等等. 读者可能觉得这些需求十分简单,马上就想到了通过for循环之类来实现.只需要在Loaded事件里添上这些元素就好了. 但这样可能存在一些问题--如果这些UI元素只是静态的,是装饰性的--虽然code-behind不用白不用,但为了这些纯静态元素将代码逻辑变得臃肿似乎略有

UWP开发中,无法向“splitview”类型对象添加内容

问题描述 求解答我看网上的demo是可以这么写的,之前也是可以的后来再打开就成这样了 解决方案 解决方案二:同问,我也遇到了这样的问题解决方案三:我知道为什么了.SplitView分为两部分,Pane和Content,写代码的时候也这样写就好了,比如:<SplitViewMargin="0,60,0,0"x:Name="mySplit"DisplayMode="CompactOverlay"CompactPaneLength="0

Win10 UWP 开发系列:使用SQLite

原文:Win10 UWP 开发系列:使用SQLite 在App开发过程中,肯定需要有一些数据要存储在本地,简单的配置可以序列化后存成文件,比如LocalSettings的方式,或保存在独立存储中.但如果数据多的话,还是需要本地数据库的支持.在UWP开发中,可以使用SQLite.本篇文章说一下如何在UWP中使用SQLite.因为SQLite是跨平台的,版本众多,我刚开始用的时候不知道要装哪个,什么WP8的.WP8.1的.Win RT的--简直摸不着头脑.希望这篇文章能让大家少走点弯路. 其实这篇文

Win 10 UWP开发系列:设置AppBarButton的图标

原文:Win 10 UWP开发系列:设置AppBarButton的图标 在WP8以前,页面最下面的四个小圆按钮是不支持绑定的,WP8.1 RT之后,系统按钮升级成了AppBarButton,并且支持绑定了.在Win10 UWP开发中,按钮的样式发生了变化,外面的圆圈没有了.不过个人还是更喜欢之前的圆按钮的样子^_^ 很喜欢Metro Studio这个程序,有数百个好看的按钮可以用,并且可以导出成png图片.但现在不建议采取png图片的方式了,主要是因为png在缩放后有可能会失真,最好使用字体.p

UWP开发入门(二)——RelativePanel

原文:UWP开发入门(二)--RelativePanel RelativePanel也是Win10 UWP新增的控件,和上篇提到的SplitView一样在UWP的UI布局起到非常重要的作用.说句实在话,这货其实就是为了UWP的Adaptive UI而特意增加的,由于他的功能和DockPanel有相当的重叠,以至于DockPanel被从Win10 SDK中被撸掉了--太惨了-- 为什么说RelativePanel可以替代DockPanel,我们可以先从几个比较重要的属性看起:AlignLeftWi

UWP开发笔记——嵌套式页面的实现

原文:UWP开发笔记--嵌套式页面的实现 绪论 UWP开发中,Page是最常用的Control之一,通常情况下,在开发的application中,每一个页面就是一个Page.有时候,为了开发整合度更高,UI表现更为一致的UI,开发者需要把UI控件和功能整合到一个页面的子页面中,子页面拥有自己的UI表现和生命周期,这就需要在Page中嵌套Page来达到需要实现的效果. 一种实现方法 其实,实现嵌套页面是一件很简单的事情,我们知道,page都是通过Frame显示和控制Navigation的,基于这点

UWP开发随笔——使用SQLite数据库

原文:UWP开发随笔--使用SQLite数据库 摘要 大多数的app都需要数据存储,在数据存储这方面,强大的windows把app数据分为两种:settings和files,并提供了十分简洁的api,让开发者能够轻松使用.但是在有些场景下,app的数据存储需要有database的支持,而sqlite,由于它轻量.高效.跨平台的特性,已经成为移动客户端开发中不可或缺的一部分.今天,小编就简单介绍一下如何在uwp开发中使用sqlite数据库. 环境配置 1.下载和安装SQLite 要使用sqlite

UWP开发入门(十六)——常见的内存泄漏的原因

原文:UWP开发入门(十六)--常见的内存泄漏的原因 本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)--用Diagnostic Tool检查内存泄漏>中提到过,即使有垃圾回收机制,写C#还是有可能发生内存泄漏. 一般来说,以下两种情况会导致内存泄漏: 对象用完了但是没有释放资源 对象本身是做了清理内存的操作,但是对象内部的子对象没有成功释放资源 下面就UWP开发中具体的实例来说明需要避免的写法 从static/glob