New UWP Community Toolkit - RadialProgressBar
概述
UWP Community Toolkit 中有一个圆形的进度条控件 - RadialProgressBar,本篇我们结合代码详细讲解 RadialProgressBar 的实现。
RadialProgressBar 是一种圆形的进度条控件,进度值用圆形中的填充色的角度来表示,进度增长,填充色按照顺时针方向增加,直到占满整个圆形,则进度条达到最大值。我们来看一下官方的介绍和官网示例中的展示:

Doc:https://docs.microsoft.com/zh-cn/windows/uwpcommunitytoolkit/controls/radialprogressbar
Namespace: Microsoft.Toolkit.Uwp.UI.Controls; Nuget: Microsoft.Toolkit.Uwp.UI.Controls;
开发过程
代码分析
我们来看一下 RadialProgressBar 控件的结构:
- RadialProgressBar.cs - RadialProgressBar 控件定义类
- RadialProgressBar.xaml - RadialProgressBar 控件样式

1. RadialProgressBar.xaml
这是 RadialProgressBar 控件的样式,我们可以看到 Template 部分由 OutlineFigurePart 和 BarFigurePart 组成,分别代表了进度条的灰色底和实际的进度条,因为两个部分的样式基本一致,所以我们省略了一部分。
可以看到,两个部分的样式组成,都是一个 Path 的几何图形,里面包含了 ParhFigure,它的 segment 属性包含了 ArcSegment:一个弧度区段;这就是样式的基本组成了。
<Style TargetType="local:RadialProgressBar" >
<Setter Property="Foreground" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
<Setter Property="Outline" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Thickness" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RadialProgressBar">
<Grid Background="{TemplateBinding Background}">
<!-- OutlineFigurePart of progress bar -->
<Path Fill="Transparent" Stroke="{TemplateBinding Outline}" StrokeThickness="{TemplateBinding Thickness}" StrokeDashCap="Flat">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="OutlineFigurePart">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment x:Name="OutlineArcPart" IsLargeArc="True" SweepDirection="Clockwise"/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<!-- BarFigurePart of Progress Bar -->
...
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
2. RadialProgressBar.cs
看一下这个类的构成:

RadialProgressBar 类继承自 ProgressBar 类,表现形式为圆形的进度条,分为 outline 和 bar 两个部分,所以可以看到类中定义了 outlineFigure、barFigure、outlineArc 和 barArc 属性;而依赖属性有:
- Thickness - 表示圆形进度条的圆环大小,默认为 0,xaml 中定义为 4
- Outline - 表示圆形底的画刷,默认为 transparent,xaml 中定义为 gray
而继承自 ProgressBar 的 Background 和 Foreground,则分别表示进度条中间空白部分的颜色,和进度条的进度颜色。因为继承自 ProgressBar 类,所以重载了 Progress 类的几个方法:
- OnMinimumChanged(old, new) - 进度条最小值变化的处理方法,会触发 RenderSegment() 方法;
- OnMaximumChanged(old, new) - 进度条最大值变化的处理方法,会触发 RenderSegment() 方法;
- OnValueChanged(old, new) - 进度条进度值变化的处理方法,会触发 RenderSegment() 方法;
- OnApplyTemplate() - 应用模板或哦模板改变时,更新控件的视觉显示 ,会触发 RenderAll() 方法;
还有两个 Changed 处理方法:ThicknessChangedHandler(d, e) 和 SizeChangedHandler(s, e),分别处理进度条宽度变化和进度条尺寸变化,也会触发 RenderAll() 方法;
下面来看看几个主要的方法:
① ComputeNormalizedRange()
根据进度条的最大值和最小值计算出的区间,以及当前值,计算出当前值在区间中占的百分比,如果当前值 > 0.999, 则取值 0.999
private double ComputeNormalizedRange()
{
var range = Maximum - Minimum;
var delta = Value - Minimum;
var output = range == 0.0 ? 0.0 : delta / range;
output = Math.Min(Math.Max(0.0, output), 0.9999);
return output;
}
② ComputeEllipseSize()
计算圆形的尺寸,根据进度条的实际宽度和高度,去掉安全宽度,计算后值的 1/2 就是 Ellipse 的长短半径;
private Size ComputeEllipseSize()
{
var safeThickness = Math.Max(Thickness, 0.0);
var width = Math.Max((ActualWidth - safeThickness) / 2.0, 0.0);
var height = Math.Max((ActualHeight - safeThickness) / 2.0, 0.0);
return new Size(width, height);
}
③ RenderSegment()
弧形区段的实际渲染,根据当前角度,尺寸和圆环宽度,计算出当前弧形的终点坐标;同时输出一个值:IsLargeArc,角度是否 >= 180 度。
private void RenderSegment()
{
if (!allTemplatePartsDefined)
{
return;
}
var normalizedRange = ComputeNormalizedRange();
* Math.PI * normalizedRange;
var size = ComputeEllipseSize();
var translationFactor = Math.Max(Thickness / 2.0, 0.0);
double x = (Math.Sin(angle) * size.Width) + size.Width + translationFactor;
) + translationFactor;
barArc.IsLargeArc = angle >= Math.PI;
barArc.Point = new Point(x, y);
}
④ RenderAll()
渲染进度条的全部控件部分,计算 outlineFigure 和 barFigure 的起始点,new Point(segmentWidth + translationFactor, translationFactor) 也就是圆形最上方的横向中心点;然后计算 outlineArc 和 barArc 的尺寸,也就是圆形半径;outlineArc 的角度固定,所以只需要给一个初始值,最后是调用 RenderSegment() 方法计算 Bar 的实际渲染部分。
private void RenderAll()
{
if (!allTemplatePartsDefined)
{
return;
}
var size = ComputeEllipseSize();
var segmentWidth = size.Width;
var translationFactor = Math.Max(Thickness / 2.0, 0.0);
outlineFigure.StartPoint = barFigure.StartPoint = new Point(segmentWidth + translationFactor, translationFactor);
outlineArc.Size = barArc.Size = new Size(segmentWidth, size.Height);
outlineArc.Point = new Point(segmentWidth + translationFactor - 0.05, translationFactor);
RenderSegment();
}
调用示例
我们定义了一个 RadialProgressBar 控件,底色是浅灰色,进度颜色是绿色,区间是 0~100,当前值是 29,进度条宽度是 20;从示例的运行图中可以印证这些数据。
<controls:RadialProgressBar
x:Name="RadialProgressBarControl"
Grid.Column="1"
Value="29"
Foreground="Green"
Thickness="20"
Minimum="0"
Maximum="100"
Width="200"
Height="200"
Outline="LightGray"/>

总结
到这里我们就把 UWP Community Toolkit 中的 RadialProgressBar 控件的源代码实现过程和简单的调用示例讲解完成了,希望能对大家更好的理解和使用这个控件有所帮助;大家也可以基于简单的圆形进度条,扩展出更多中不同形状的进度条,例如矩形,实心圆形等等,欢迎大家多多交流,谢谢!
最后,再跟大家安利一下 UWPCommunityToolkit 的官方微博:https://weibo.com/u/6506046490, 大家可以通过微博关注最新动态。
衷心感谢 UWPCommunityToolkit 的作者们杰出的工作,Thank you so much, UWPCommunityToolkit authors!!!
New UWP Community Toolkit - RadialProgressBar的更多相关文章
- New UWP Community Toolkit
概述 UWP Community Toolkit 是一个 UWP App 自定义控件.应用服务和帮助方法的集合,能够很大程度的简化和指引开发者的开发工作,相信广大 UWPer 并不陌生. 下面是截取自 ...
- New UWP Community Toolkit - XAML Brushes
概述 上一篇 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾.接下来会针对每个重要更新,结合 SDK 源代码和调用代码详细讲解. 本篇我们 ...
- New UWP Community Toolkit - Markdown
概述 前面 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 MarkdownTextBlock 和 MarkdownDoc ...
- New UWP Community Toolkit - Staggered panel
概述 前面 New UWP Community Toolkit 文章中,我们对 2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 Staggered panel,本篇我们结合代码详细讲解 St ...
- New UWP Community Toolkit - Carousel
概述 New UWP Community Toolkit V2.2.0 的版本发布日志中提到了 Carousel 的调整,本篇我们结合代码详细讲解 Carousel 的实现. Carousel 是 ...
- New UWP Community Toolkit - RadialGauge
概述 New UWP Community Toolkit V2.2.0 的版本发布日志中提到了 RadialGauge 的调整,本篇我们结合代码详细讲解 RadialGauge 的实现. Radi ...
- New UWP Community Toolkit - RangeSelector
概述 前面 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 RangeSelector,本篇我们结合代码详细讲解一下 Ra ...
- New UWP Community Toolkit - ImageEx
概述 UWP Community Toolkit 中有一个图片的扩展控件 - ImageEx,本篇我们结合代码详细讲解 ImageEx 的实现. ImageEx 是一个图片的扩展控件,包括 Ima ...
- New UWP Community Toolkit - AdaptiveGridView
概述 UWP Community Toolkit 中有一个自适应的 GridView 控件 - AdaptiveGridView,本篇我们结合代码详细讲解 AdaptiveGridView 的实现 ...
随机推荐
- IOS开发之XCode学习007:UIWindow对象
此文学习来源为:http://study.163.com/course/introduction/1002858003.htm #import "AppDelegate.h" @i ...
- C#图解教程 第十九章 LINQ
LINQ 什么是LINQLINQ提供程序 匿名类型 方法语法和查询语法查询变量查询表达式的结构 from子句join子句什么是联结查询主体中的from-let-where片段 from子句let子句w ...
- ASP.NET CSS 小结
1.ASP.NET 引用CSS 1.Site.master里面设置webopt <webopt:bundlereferencerunat="server"path=" ...
- 安卓中webview读取html,同时嵌入Flex的SWF,交互
安卓中webview读取html,同时嵌入Flex的SWF,交互 安卓activity与html交互很简单,用javascript接口即可,网上一堆的例子,基本上没多大问题. 在html里面嵌入swf ...
- 【BZOJ2037】Sue的小球(动态规划)
[BZOJ2037]Sue的小球(动态规划) 题面 BZOJ 题解 莫名想到这道题目 很明显是一样的 设\(f[i][j][0/1]\)表示已经接到了\(i-j\)这一段的小球 当前在\(i\)或者在 ...
- HDU4812
树分治 求逆元请递推,不然会TLE 开桶记录即可 注意常数 # pragma comment(linker,"/STACK:102400000,102400000") # incl ...
- [BZOJ1604] [Usaco2008 Open] Cow Neighborhoods 奶牛的邻居 (queue & set)
Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l ...
- 8Manage:物流CRM,深度挖掘快递企业下一站蓝海!
[导读]网购的普及加快了快递物流服务在中国的发展,而物流行业也开始展露出自身巨大的发展潜力和进步空间.其中,作为物流行业根本核心的物流客户关系管理开始引起了管理者的注意,如何升级用户物流服务体验,把握 ...
- Chrome游览器使用时,修改文件和网页刷新后,不能显示效果
一:因为游览器缓存问题 有时候在写完代码后,刷新游览器,发现自己写的目标是让某一个东西隐藏,但是结果是依旧显示着,打开调试工具在Sources中发现,文件依旧是上次的旧的文件,新文件没有加载进去,无论 ...
- eclipse的注释
版权声明:本文为博主原创文章,转载请注明出处. 如果能帮助你,那我的目的就达到了 Window --> Java --> Code Style --> Code Templates ...