本篇我们通过绘制一个非常简单的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. rocketmq总结

    1:角色关系 2:顺序消息 消费消息的顺序要同収送消息的顺序一致,在 RocketMQ 中,主要挃的是尿部顺序,即一类消息为满足顺序性,必须 Producer 单线程顺序収送,丏収送到同一个队列,返样 ...

  2. 收不到Win10正式版预订通知?一个批处理搞定

    目前,已经有不少Win7.Win8.1用户在系统右下角收到Win10正式版的预订提示窗口.点击接受预订后,系统会将Win10正式版所需的安装文件提前下载好,7月29日正式发布的时候,就可以第一时间升级 ...

  3. Scala 深入浅出实战经典 第57讲:Scala中Dependency Injection实战详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  4. webpack处理Img标签路径的几种情况

    在使用webpack过程中遇到这个问题,各种搜索遇到此问题的还真不少,但都没有一个完整的说明. 后来研究下,图片除了路径替换还是就是图片做优化主是小于一定大小的通过转 base64 inline方式减 ...

  5. ecshop 加广告出现广告位的宽度值必须在1到1024之间

    打开 admin/ad_position.php这个文件,搜索1024,这里你会搜到两个地方 在236行左右 if ($ad_width > 1024 || $ad_width < 1) ...

  6. iOS 实现快速切换主题详细教程(附上源码)

    前言 iOS 实现主题切换,相信在未来的app里也是会频繁出现的,尽管现在只是出现在主流的APP,如(QQ.新浪微博.酷狗音乐.网易云音乐等),但是现在是看颜值.追求个性的年代,所以根据用户喜好自定义 ...

  7. 云计算的三层SPI模型

    (转自:http://hi.baidu.com/fengjun8216/item/b15bbef4dcf74049922af27b) 一般而言,云计算架构可以用三层SPI模型来表述. 一.基础设施即服 ...

  8. Carthage 安装和使用

    和Cocoapods相比各有利弊吧,具体对比参见: Carthage 初探:四大优势与四大劣势 第一步:如果没有安装Homebrew先安装 打开命令终端,直接输入以下命令回车 /usr/bin/rub ...

  9. centos 7 中 tomcat 安装

    一. 安装 jdk [root@iZm5ei4m ~]# /usr/local/tomcat/bin/startup.sh 一.安装 jdk 二.设置环境变量 #################### ...

  10. android 开发 - 使用okhttp框架封装的开发框架

    概述 在android开发中经常要访问网络,目前最流行的网络访问框架就是Okhttp了,然而我们在具体使用时,往往仍然需要二次封装.我使用Builder设计模式进行了封装形成oknet开源库. 介绍 ...