本篇我们通过绘制一个非常简单的UserControl控件,来分享一下对Adaptive UI的理解及一些图形绘制的技巧。

  现在流行的APP都少不了精致的用户头像,首先假设我们需要绘制如下的图形作为默认头像:

  

<UserControl
x:Class="AdaptiveUserControl.Circle0"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AdaptiveUserControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"> <Grid Width="50" Height="50" CacheMode="BitmapCache">
<Ellipse Fill="Gray"></Ellipse>
<Ellipse Width="42" Height="42" Fill="White"></Ellipse>
<Ellipse Width="34" Height="34" Fill="Green"></Ellipse>
<TextBlock Text="F" TextAlignment="Center" VerticalAlignment="Center" TextLineBounds="Tight" Foreground="White"></TextBlock>
</Grid>
</UserControl>

  实现较为简单,堆叠了三个Ellipse来实现三层圆环的效果。其中三层圆环的间距通过Width和Height来实现。

  通常情况下,该实现已经可以满足我们的要求了。

  再来看第二个实现:

    <Grid CacheMode="BitmapCache" >
<Ellipse Fill="Gray"></Ellipse>
<Ellipse Margin="4" Fill="White"></Ellipse>
<Ellipse Margin="8" Fill="Green"></Ellipse>
<TextBlock Text="F" TextAlignment="Center" VerticalAlignment="Center" TextLineBounds="Tight" Foreground="White"></TextBlock>
</Grid>

  稍有不同,具体的Width和Height已经不再设置了,三层圆环的间距通过Margin来实现。

  接下来看第三个实现:

    <Grid CacheMode="BitmapCache">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="8*"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="8*"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Ellipse Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="5" Grid.RowSpan="5" Fill="Gray"></Ellipse>
<Ellipse Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="3" Grid.RowSpan="3" Fill="White"></Ellipse>
<Ellipse Grid.Column="2" Grid.Row="2" Fill="Green"></Ellipse>
<TextBlock Grid.Column="2" Grid.Row="2" Text="F" TextAlignment="Center" VerticalAlignment="Center" TextLineBounds="Tight" Foreground="White"></TextBlock>
</Grid>

  第三个实现已经不包含任何关于长度以及高度的数字了。所有的元素均按照比例来缩放。这样做的好处在哪里呢。我们实际使用这三个UserControl来看看:

  

    <Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions> <local:Circle0 ></local:Circle0>
<local:Circle0 Grid.Column="1" Width="25" Height="25" FontSize="10"></local:Circle0>
<local:Circle0 Grid.Column="2" Width="100" Height="100" FontSize="30"></local:Circle0> <local:Circle1 Grid.Row="1" Width="50" Height="50"></local:Circle1>
<local:Circle1 Grid.Row="1" Grid.Column="1" Width="25" Height="25" FontSize="10"></local:Circle1>
<local:Circle1 Grid.Row="1" Grid.Column="2" Width="100" Height="100" FontSize="30"></local:Circle1> <local:Circle2 Grid.Row="2" Width="50" Height="50"></local:Circle2>
<local:Circle2 Grid.Row="2" Grid.Column="1" Width="25" Height="25" FontSize="10"></local:Circle2>
<local:Circle2 Grid.Row="2" Grid.Column="2" Width="100" Height="100" FontSize="30"></local:Circle2>
</Grid>

  首先由于第一种写法定死了Width和Height,可以看到第一排的圆形在尺寸变化时无法自适应大小,悲剧的被截断或者无法撑开。

  第二种写法的问题在于间距被固定,虽然整体可以自动缩放,但间距仍需要通过代码去修正才能保持比例。

  第三种自然是最佳做法,无论尺寸如何变化,均可以自适应。

  回顾一下之前对Adaptive Ui布局技巧的总结:

  1. 尽量不要有写死的Width和Height
  2. 可以有少量的Margin
  3. 整体为纵向布局的界面(比如手机竖着拿),横向可以有写死的数字,纵向最好按比例。反之亦然。

  

  这里还有几个问题需要说明一下:

  • CacheMode="BitmapCache"

  堆叠的Shape图形,我们这里是三个Circle,会导致重复的绘制影响性能。不要忘记加上CacheMode="BitmapCache"来告诉系统避免该问题。

  MSDN的原文如下:

  过度绘制的另一个来源是由许多重叠元素形成的形状。 如果针对包含合成形状的 UIElement,将 CacheMode 设置为 BitmapCache,平台会将该元素作为位图呈现一次,然后每帧使用该位图而不是过度绘制。

  • 三种画法的性能差距

  我做了一个去除了虚拟化的ListView进行测试,各放置1000个圆形图像。三种画法的性能差距基本一致,没有太大差别,请放心使用。在可以正常虚拟化的ListView中就更没有问题了。

  • 还是性能问题

  非常遗憾,无论是DrawingVisual和DrawingContext这类底层的高性能的绘图类,还是RadialGradientBrush径向渐变的画刷。一切可以进一步提升性能的方式,在从WPF-》Silverlight-》UWP的演化过程中,尼玛都退化了,木有了!!!就UWP本身而言,不存在更好的绘制方式了,老老实实通过Shape来堆叠图形吧……

  最后GitHub:

  https://github.com/manupstairs/UWPSamples/tree/master/UWPSamples/AdaptiveUserControl

UWP开发入门(十四)—— UserControl中Adaptive UI的小技巧的更多相关文章

  1. UWP开发入门(四)——自定义CommandBar

    各位好,再次回到UWP开发入门系列,刚回归可能有些不适应,所以今天我们讲个简单的,自定义CommandBar,说通俗点就是自定义类似AppBarButton的东西,然后扔到CommandBar中使用. ...

  2. UWP开发入门(二十一)——保持Ui线程处于响应状态

    GUI的程序有时候会因为等待一个耗时操作完成,导致界面卡死.本篇我们就UWP开发中可能遇到的情况,来讨论如何优化处理. 假设当前存在点击按钮跳转页面的操作,通过按钮打开的新页面,在初始化过程中存在一些 ...

  3. UWP开发入门(十)——通过继承来扩展ListView

    本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念.而是通过继承的方法来扩展一个现有的类,在继承的 ...

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

    本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...

  5. UWP开发入门系列笔记之(一):UWP初览

    标签: 随着微软Build2015带来的好消息,Win10正式版发布的日子已经离我们越来越近了,我们也终于欣喜地看到:一个统一的Windows平台对于开发人员来说充满了吸引力,这局棋下的好大的说--于 ...

  6. SLAM十四讲中Sophus库安装

    Sophus截止目前有很多版本,其中大体分为两类,一种是用模板实现的方法,一种是用非模板类实现的,SLAM十四讲中使用的是非模板类库,clone Sophus: git clone http://gi ...

  7. UWP开发入门(25)——通过Radio控制Bluetooth, WiFi

    回顾写了许久的UWP开发入门,竟然没有讲过通过Windows.Devices.Radios.Radio来控制Bluetooth和WiFi等功能的开关.也许是因为相关的API设计的简单好用,以至于被我给 ...

  8. [转]Golang 中使用 JSON 的小技巧

    taowen是json-iterator的作者. 序列化和反序列化需要处理JSON和struct的关系,其中会用到一些技巧. 原文 Golang 中使用 JSON 的小技巧是他的经验之谈,介绍了一些s ...

  9. IDEA Intellij中vim插件使用小技巧

    在 IDEA Intellij小技巧和插件 一文中简单介绍了一下IdeaVim插件.在这里详细总结一下这个插件在日常编程中的一些常用小技巧.供有兴趣使用这个插件,但对Vim还不十分熟悉的朋友参考.当然 ...

随机推荐

  1. zz A list of open source C++ libraries

    A list of open source C++ libraries < cpp‎ | links http://en.cppreference.com/w/cpp/links/libs Th ...

  2. select选择框内容左右移动添加删除栏(升级)

    先看一下之前的版本(10年前的作品了) 新版增加了拖动事件(双向及本列),双击左右自动移动,修正了算法性能更好: 也更新了如果姓名长度太长显示变形问题

  3. 《CSS 设计指南》学习笔记 一

    本篇文章是对这几天看完 Charles Wyke-Smit 的 <CSS 设计指南> 后的一些学习笔记与心得,笔者好像是大一的时候开始接触网页设计,由于并不是计算机专业的,所以所有都是自己 ...

  4. Linux--Ubuntu12.04下安装JDK

    前言 在Ubuntu中安装JDK的方法非常的多,网上现在介绍的很多方法,都不是很清楚,对于初学者,很多都不太明白如何安装.本篇博客就Ubuntu下安装JDK进行详细的讲解,这里使用的Ubuntu版本为 ...

  5. Codeforces Round #379 (Div. 2) C. Anton and Making Potions 枚举+二分

    C. Anton and Making Potions 题目连接: http://codeforces.com/contest/734/problem/C Description Anton is p ...

  6. Windows 8 图标前面的勾选

    http://bbs.pcbeta.com/viewthread-999730-1-1.html 不管是桌面的图标还是资源管理器中的图标之前都出现了一个小小的方框.选中图标的时候会自动勾选那个框,如果 ...

  7. 面向.Net程序员的Sql版本管理

    代码版本管理基本上程序员们都知道 TFS GIT SVN等等 但是对于数据库版本管理 java程序员或许会了解一些 但是.Net程序员收获的资料应该不多. 特别是现在云概念使用越来越广的情况下,与应用 ...

  8. windows下Android利用ant自动编译、修改配置文件、批量多渠道,打包生成apk文件

    原创文章,转载请注明:http://www.cnblogs.com/ycxyyzw/p/4535459.html android 程序打包成apk,如果在是命令行方式,一般都要经过如下步骤: 1.用a ...

  9. Rxlifecycle(三):坑

    坑1 Observable.just("hello world!") .compose(this.<String>bindUntilEvent(ActivityEven ...

  10. openssl - rsa加解密例程

    原文链接: http://www.cnblogs.com/cswuyg/p/3187462.html openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密.可以使用非对称加 ...