Windows Community Toolkit 3.0 - UniformGrid
概述
UniformGrid 控件是一个响应式的布局控件,允许把 items 排列在一组均匀分布的行或列中,以填充整体的可用显示空间,形成均匀的多个网格。默认情况下,网格中的每个单元格大小相同。
这是一个非常实用的控件,比如相册应用中多行多列均匀排列图片,比如新闻类应用中排列新闻,再比如我们在来画视频中展示用户作品封面和简要信息等,因为它支持响应布局,所以在应用尺寸变化时显示会很友好。
下面是 Windows Community Toolkit Sample App 的示例截图和 code/doc 地址:
Windows Community Toolkit Doc - UniformGrid
Windows Community Toolkit Source Code - UniformGrid
Namespace: Microsoft.Toolkit.Uwp.UI.Controls; Nuget: Microsoft.Toolkit.Uwp.UI.Controls;
开发过程
代码结构分析
首先来看 UniformGrid 控件的代码结构:
- TakenSpotsReferenceHolder.cs - 获取和设置点数组,标识布局中的 item 是否固定;
- UniformGrid.Helpers.cs - UniformGrid 控件帮助类,主要处理控件的行列布局和排列逻辑;
- UniformGrid.Properties.cs - UniformGrid 控件的依赖属性类;
- UniformGrid.cs - UniformGrid 控件的主要处理逻辑类;
UniformGrid 控件的代码实现比较简单,我们来看几个类中重要的方法:
1. UniformGrid.Helpers.cs
1). GetFreeSpot()
获取目前 UniformGrid 控件中可用的点,分为上下和左右两个方向,分别处理行和列的数据;以行为例,遍历每列的所有行,返回是否可用于放置元素的标识;
internal static IEnumerable<(int row, int column)> GetFreeSpot(TakenSpotsReferenceHolder arrayref, int firstcolumn, bool topdown) { if (topdown) { ); // Layout spots from Top-Bottom, Left-Right (right-left handled automatically by Grid with Flow-Direction). // Effectively transpose the Grid Layout. ; c < arrayref.SpotsTaken.GetLength(); c++) { && firstcolumn > && firstcolumn < rows) ? firstcolumn : ; for (int r = start; r < rows; r++) { if (!arrayref.SpotsTaken[r, c]) { yield return (r, c); } } } } else { // 省略列处理代码 ... } }
2). GetDimensions()
获取 UniformGrid 控件在行和列的数值;先计算目前所有 item 所需的格数,分为 row = 0,column = 0 和两个值都为 0 处理,分别计算 row column 的值;如果两个值有一个为 0,则根据不为 0 的值和 item 数量来判断另一个值;如果两个值都为 0,则定义为方形;
internal static (int rows, int columns) GetDimensions(FrameworkElement[] visible, int rows, int cols, int firstColumn) { // If a dimension isn't specified, we need to figure out the other one (or both). || cols == ) { // Calculate the size & area of all objects in the grid to know how much space we need. , visible.Sum(item => GetRowSpan(item) * GetColumnSpan(item))); ) { ) { // Bound check ) ? : firstColumn; // If we have columns but no rows, calculate rows based on column offset and number of children. rows = (count + first + (cols - )) / cols; return (rows, cols); } else { // Otherwise, determine square layout if both are zero. var size = (int)Math.Ceiling(Math.Sqrt(count)); // Figure out if firstColumn is in bounds ) ? : firstColumn; rows = (int)Math.Ceiling(Math.Sqrt(count + first)); return (rows, rows); } } ) { ... } } return (rows, cols); }
3). SetupRowDefinitions()
SetupRowDefinitions() 和 SetupColumnDefinitions() 实现类似,我们看其中一个;先初始化行定义,遍历行列表,如果有行的布局方式不为自动布局,先把这些布局删掉,再重新以自动布局的方式加入到行定义中;这样实现的目标,是保证行布局能对 item 自适应,缩放时可以自动响应;
internal void SetupRowDefinitions(int rows) { // Mark initial definitions so we don't erase them. foreach (var rd in RowDefinitions) { if (GetAutoLayout(rd) == null) { SetAutoLayout(rd, false); } } // Remove non-autolayout rows we've added and then add them in the right spots. if (rows != RowDefinitions.Count) { ; r >= ; r--) { if (GetAutoLayout(RowDefinitions[r]) == true) { RowDefinitions.RemoveAt(r); } } for (int r = this.RowDefinitions.Count; r < rows; r++) { var rd = new RowDefinition(); SetAutoLayout(rd, true); this.RowDefinitions.Insert(r, rd); } } }
2. UniformGrid.Properties.cs
该类定义了 UniformGrid 控件所需的依赖属性,主要有:
- AutoLayout - 获取和设置自动布局属性,包括对行和列的操作;
- Columns - UniformGrid 的列属性;
- FirstColumn - UniformGrid 的首列属性,获取的是首行元素距离第一列的偏移量;
- Orientation - UniformGrid 的排列方式,包括横向和纵向两种;
- Rows - UniformGrid 的行属性;
3. UniformGrid.cs
该类主要是 UnifromGrid 在 Grid 类基础上的处理,主要处理测量和排列的方法,我们来看一下功能比较复杂的 MeasureOverride() 方法,ArrangeOverride() 方法实现很简单,这里不做分析。
1). MeasureOverride()
- 首先根据可见元素集合,获取控件的行列数量,设置行列定义;
- 遍历所有可见元素,根据每个元素的行列和行列跨度属性,设置自动布局,填充 spotsTaken;
- 计算行和列的空白空间总数值,再根据总空间数值和行列数,计算出一个元素的尺寸;
- 遍历所有可见元素,找出元素中最大的宽度和高度;再用这个最大尺寸,乘上行列数,加上空白空间数值,得到控件所需尺寸;
protected override Size MeasureOverride(Size availableSize) { // Get all Visible FrameworkElement Children var visible = Children.Where(item => item.Visibility != Visibility.Collapsed && item is FrameworkElement).Select(item => item as FrameworkElement).ToArray(); var (rows, columns) = GetDimensions(visible, Rows, Columns, FirstColumn); SetupRowDefinitions(rows); SetupColumnDefinitions(columns); var spotref = new TakenSpotsReferenceHolder(rows, columns); foreach (var child in visible) { var row = GetRow(child); var col = GetColumn(child); var rowspan = GetRowSpan(child); var colspan = GetColumnSpan(child); && col == && GetAutoLayout(child) == null) || GetAutoLayout(child) == true) { SetAutoLayout(child, true); } else { SetAutoLayout(child, false); spotref.SpotsTaken.Fill(true, row, col, colspan, rowspan); // row, col, width, height } } ; ; if (_hasGridSpacing) { columnSpacingSize = ColumnSpacing * (columns - ); rowSpacingSize = RowSpacing * (rows - ); } Size childSize = new Size( (availableSize.Width - columnSpacingSize) / columns, (availableSize.Height - rowSpacingSize) / rows); double maxWidth = 0.0; double maxHeight = 0.0; var freespots = GetFreeSpot(spotref, FirstColumn, Orientation == Orientation.Vertical).GetEnumerator(); foreach (var child in visible) { if (GetAutoLayout(child) == true) { if (freespots.MoveNext()) { var (row, column) = freespots.Current; SetRow(child, row); SetColumn(child, column); var rowspan = GetRowSpan(child); var colspan = GetColumnSpan(child); || colspan > ) { spotref.SpotsTaken.Fill(true, row, column, GetColumnSpan(child), GetRowSpan(child)); // row, col, width, height } } else { child.Measure(Size.Empty); _overflow.Add(child); continue; } } || GetRow(child) >= rows || GetColumn(child) < || GetColumn(child) >= columns) { child.Measure(Size.Empty); _overflow.Add(child); continue; } child.Measure(childSize); maxWidth = Math.Max(child.DesiredSize.Width, maxWidth); maxHeight = Math.Max(child.DesiredSize.Height, maxHeight); } var desiredSize = new Size((maxWidth * (double)columns) + columnSpacingSize, (maxHeight * (double)rows) + rowSpacingSize); base.MeasureOverride(desiredSize); return desiredSize; }
调用示例
UniformGrid 控件的调用非常简单,下面看看 XAML 中的调用:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <controls:UniformGrid FirstColumn="1" Orientation="Horizontal" Rows="0" Columns="0"> <Border Background="AliceBlue" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="2"><TextBlock Text="1"/></Border> <Border Background="Cornsilk"><TextBlock Text="2"/></Border> <Border Background="DarkSalmon"><TextBlock Text="3"/></Border> <Border Background="Gainsboro"><TextBlock Text="4"/></Border> <Border Background="LightBlue"><TextBlock Text="5"/></Border> <Border Background="MediumAquamarine"><TextBlock Text="6"/></Border> <Border Background="MistyRose"><TextBlock Text="7"/></Border> <Border Background="LightCyan"><TextBlock Text="8"/></Border> <Border Background="Salmon"><TextBlock Text="9"/></Border> <Border Background="Goldenrod"><TextBlock Text="10"/></Border> <Border Background="Pink"><TextBlock Text="11"/></Border> </controls:UniformGrid> </Page>
总结
到这里我们就把 Windows Community Toolkit 3.0 中的 UniformGrid 的源代码实现过程讲解完成了,希望能对大家更好的理解和使用这个功能有所帮助。
最后,再跟大家安利一下 WindowsCommunityToolkit 的官方微博:https://weibo.com/u/6506046490, 大家可以通过微博关注最新动态。
衷心感谢 WindowsCommunityToolkit 的作者们杰出的工作,感谢每一位贡献者,Thank you so much, ALL WindowsCommunityToolkit AUTHORS !!!
Windows Community Toolkit 3.0 - UniformGrid的更多相关文章
- Windows Community Toolkit 3.0 新功能 在WinForms 和 WPF 使用 UWP 控件
本文告诉大家一个令人震惊的消息,Windows Community Toolkit 有一个大更新,现在的版本是 3.0 .最大的提升就是 WinForm 和 WPF 程序可以使用部分 UWP 控件. ...
- Windows Community Toolkit 4.0 - DataGrid - Part03
概述 在上面一篇 Windows Community Toolkit 4.0 - DataGrid - Part02 中,我们针对 DataGrid 控件的 Utilities 部分做了详细分享.而在 ...
- Windows Community Toolkit 4.0 - DataGrid - Part02
概述 在上面一篇 Windows Community Toolkit 4.0 - DataGrid - Part01 中,我们针对 DataGrid 控件的 CollectionView 部分做了详细 ...
- Windows Community Toolkit 4.0 - DataGrid - Part01
概述 在上面一篇 Windows Community Toolkit 4.0 - DataGrid - Overview 中,我们对 DataGrid 控件做了一个概览的介绍,今天开始我们会做进一步的 ...
- Windows Community Toolkit 4.0 - DataGrid - Overview
概述 Windows Community Toolkit 4.0 于 2018 月 8 月初发布:Windows Community Toolkit 4.0 Release Note. 4.0 版本相 ...
- Windows Community Toolkit 3.0 - InfiniteCanvas
概述 InfiniteCanvas 是一个 Canvas 控件,它支持无限画布的滚动,支持 Ink,文本,格式文本,画布缩放操作,撤销重做操作,导入和导出数据. 这是一个非常实用的控件,在“来画视频” ...
- Windows Community Toolkit 3.0 - Gaze Interaction
概述 Gaze Input & Tracking - 也就是视觉输入和跟踪,是一种和鼠标/触摸屏输入非常不一样的交互方式,利用人类眼球的识别和眼球方向角度的跟踪,来判断人眼的目标和意图,从而非 ...
- Windows Community Toolkit 3.0 - CameraPreview
概述 Windows Community Toolkit 3.0 于 2018 年 6 月 2 日 Release,同时正式更名为 Windows Community Toolkit,原名为 UWP ...
- 与众不同 windows phone (44) - 8.0 位置和地图
[源码下载] 与众不同 windows phone (44) - 8.0 位置和地图 作者:webabcd 介绍与众不同 windows phone 8.0 之 位置和地图 位置(GPS) - Loc ...
随机推荐
- [20170612]FOR ALL COLUMNS SIZE repeat(12c).txt
[20170612]FOR ALL COLUMNS SIZE repeat(12c).txt --//昨天看了https://jonathanlewis.wordpress.com/2017/06/0 ...
- Navicat 连接MySQL数据库 报错2059 - authentication plugin 'caching_sha2_password'的解决办法
#在数据库的命令行中输入以下代码即可解决,密码必须要修改 可以再次执行将密码改回来. use mysql; ALTER USER 'root'@'localhost' IDENTIFIED WITH ...
- SQL Server 事务隔离级别
一.事务隔离级别控制着事务的如下表现: 读取数据时是否占用锁以及所请求的锁类型. 占用读取锁的时间. 引用其他事务修改的行的读操作是否: 在该行上的排他锁被释放之前阻塞其他事务. 检索在启动语句或事务 ...
- js 3d图形
使用Three.js在网上中进行3D图形的展示 Three.js的官网https://threejs.org/ 第一个Demo,生成一个旋转的正方体 <style> canvas { wi ...
- esxi网络中虚拟机的相关操作
一个虚拟机的克隆就是原始虚拟机全部状态的一个备份或镜像.克隆的过程不影响原始虚拟机.而快照指的是虚拟磁盘在某一特定时间点的副本.执行快照将保留虚拟机的状况和数据. 一.实验拓扑图: 目标:克隆虚拟机, ...
- 聚类——GAKFCM的matlab程序
聚类——GAKFCM的matlab程序 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 在聚类——GAKFCM文章中已介绍了GAKFCM算法的理论知识, ...
- 【Linux常见问题】Centos7的网络配置问题
在配置Centos7网络的时候,可能出出现虚拟机.本地以及外网三者之间ping不通的问题,可以从以下的几个方面排查: 1.确定需要管理员权限才能修改配置网络,如下图: 需要点下更改设置,然后出现下面的 ...
- FastJSON、Gson和Jackson性能对比
Java处理JSON数据有三个比较流行的类库FastJSON.Gson和Jackson.本文将测试这三个类库在JSON序列化和反序列化的方面表现,主要测试JSON序列化和反序列化的速度.为了防止由于内 ...
- 设计模式のCompositePattern(组合模式)----结构模式
一.产生背景 又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式,它创建了对象组的树形结构. 这种模 ...
- github 遇到Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts问题解决
刚开始使用github的时候不是很了解,新手一般的都会遇到这个问题Permanently added the RSA host key for IP address '192.30.252.128' ...