概述

UWP Community Toolkit  中有一个圆形的进度条控件 - RadialProgressBar,本篇我们结合代码详细讲解  RadialProgressBar 的实现。

RadialProgressBar 是一种圆形的进度条控件,进度值用圆形中的填充色的角度来表示,进度增长,填充色按照顺时针方向增加,直到占满整个圆形,则进度条达到最大值。我们来看一下官方的介绍和官网示例中的展示:

Source: https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/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的更多相关文章

  1. New UWP Community Toolkit

    概述 UWP Community Toolkit 是一个 UWP App 自定义控件.应用服务和帮助方法的集合,能够很大程度的简化和指引开发者的开发工作,相信广大 UWPer 并不陌生. 下面是截取自 ...

  2. New UWP Community Toolkit - XAML Brushes

    概述 上一篇 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾.接下来会针对每个重要更新,结合 SDK 源代码和调用代码详细讲解. 本篇我们 ...

  3. New UWP Community Toolkit - Markdown

    概述 前面 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 MarkdownTextBlock 和 MarkdownDoc ...

  4. New UWP Community Toolkit - Staggered panel

    概述 前面 New UWP Community Toolkit 文章中,我们对 2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 Staggered panel,本篇我们结合代码详细讲解  St ...

  5. New UWP Community Toolkit - Carousel

    概述 New UWP Community Toolkit  V2.2.0 的版本发布日志中提到了 Carousel 的调整,本篇我们结合代码详细讲解  Carousel 的实现. Carousel 是 ...

  6. New UWP Community Toolkit - RadialGauge

    概述 New UWP Community Toolkit  V2.2.0 的版本发布日志中提到了 RadialGauge 的调整,本篇我们结合代码详细讲解  RadialGauge 的实现. Radi ...

  7. New UWP Community Toolkit - RangeSelector

    概述 前面 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾,其中简单介绍了 RangeSelector,本篇我们结合代码详细讲解一下 Ra ...

  8. New UWP Community Toolkit - ImageEx

    概述 UWP Community Toolkit  中有一个图片的扩展控件 - ImageEx,本篇我们结合代码详细讲解  ImageEx 的实现. ImageEx 是一个图片的扩展控件,包括 Ima ...

  9. New UWP Community Toolkit - AdaptiveGridView

    概述 UWP Community Toolkit  中有一个自适应的 GridView 控件 - AdaptiveGridView,本篇我们结合代码详细讲解  AdaptiveGridView 的实现 ...

随机推荐

  1. JavaScript控制输入框中只能输入中文、数字和英文

    1.问题背景 遇到这样一个问题:有一个输入框,要求只能输入中文.数字和英文(即过滤特殊字符串) 2.JS代码 function  checkUsername() { //正则表达式 var reg = ...

  2. 如何给filter添加自定义接口及调用

    本例子是在VirtualCamera的基础上添加的自定义接口用来实现exe控制osd的显示. 1. 接口部分 #ifndef __H_MyFilter__#define __H_MyFilter__# ...

  3. PyCharm 2017.3 下载与安装

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.下载 (1).下载链接: https://www.jetbrains.com/pycharm ...

  4. spring+jidi读取property的配置文件

    在Spring项目中,你可能需要从properties文件中读入配置注入到bean中,例如数据库连接信息,memcached server的地址端口信息等,这些配置信息最好独立于jar包或者war包, ...

  5. Metrics.net + influxdb + grafana 构建WebAPI的自动化监控和预警

    前言 这次主要分享通过Metrics.net + influxdb + grafana 构建WebAPI的自动化监控和预警方案.通过执行耗时,定位哪些接口拖累了服务的性能:通过请求频次,设置适当的限流 ...

  6. 深度学习框架: Keras官方中文版文档正式发布

    今年 1 月 12 日,Keras 作者 François Chollet‏ 在推特上表示因为中文读者的广泛关注,他已经在 GitHub 上展开了一个 Keras 中文文档项目.而昨日,Françoi ...

  7. 【Luogu1345】奶牛的电信(网络流)

    [Luogu1345]奶牛的电信(网络流) 题面 题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成 ...

  8. [BZOJ4071][APIO2015]八邻旁之桥

    BZOJ(这题是BZOJ权限题,有权限号的就去看看吧) Luogu(良心洛谷) 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好 ...

  9. BZOJ 1123:城市道路

    Sol 就是求割点,把贡献算一下就好...直接tarjan # include <bits/stdc++.h> # define RG register # define IL inlin ...

  10. c#多线程同步之EventWaitHandle再次使用

    /// <summary> /// 文件传输器,用来获取全文文件,自动根据全文文件数量,开启一定数量的线程,采用生产者消费模式 /// </summary> public cl ...