New UWP Community Toolkit - RadialProgressBar

来源:https://www.cnblogs.com/shaomeng/archive/2018/04/01/8678690.html
-Advertisement-
Play Games

概述 UWP Community Toolkit 中有一個圓形的進度條控制項 - RadialProgressBar,本篇我們結合代碼詳細講解 RadialProgressBar 的實現。 RadialProgressBar 是一種圓形的進度條控制項,進度值用圓形中的填充色的角度來表示,進度增長,填充色 ...


概述

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();

    var angle = 2 * 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;
    double y = (((Math.Cos(angle) * size.Height) - size.Height) * -1) + 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!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在日常 python 開發過程中,瞭解一些常用工具很有必要。例如pip,pydoc等 pip pydoc 1、pip 安裝Module 從python 2.7.9 之後,引入了pip工具,用於安裝module。 基本使用: 如果你的Python還沒有安裝pip,可以先通過下麵命令安裝pip: pyt ...
  • 一、Redis的安裝 xshell連上伺服器,依次輸入以下代碼: 如果不巧發生以下截圖中的錯誤: 說明未安裝gcc,如果是centos系統,輸入:yum install gcc安裝gcc即可,然後再次輸入make執行。 輸入make後,很不幸,再次發生如下截圖錯誤: 推測是因為編譯庫的問題。 將ma ...
  • 第二章、線性表 一、線性表的順序表示和實現 1、線性表中第i個數據元素ai的存儲位置: LOC(ai)=LOC(a1)+(i-1)*l l為每個元素需占用l個單元 2、有上式可知,線性表的順序結構是一種隨機存取的存儲結構,但其缺點為插入和刪除比較困難。 3、線性表的數據結構表示為: // 線性表的動 ...
  • 前言 從今天開始進入Java基礎的複習,可能一個星期會有一篇的,我寫博文的未必都是正確的~如果有寫錯的地方請大家多多包涵並指正~ 今天要複習的是泛型,泛型在Java中也是個很重要的知識點,本文主要講解基礎的概念,並不是高深的知識,如果基礎好的同學可以當複習看看~ 一、什麼是泛型? Java泛型設計原 ...
  • 將數據處理移植到STM32上,採用串口的DMA接收模式,註意的是DMA_MODE採用Circular,DMA_BufferSize>(8*512+36=4132)(小包8個位元組,每秒512個,完整的大包36個位元組) 代碼如下: //////////////////////////////////// ...
  • 概述 New UWP Community Toolkit V2.2.0 的版本發佈日誌中提到了 RadialGauge 的調整,本篇我們結合代碼詳細講解 RadialGauge 的實現。 RadialGauge 是一種徑向儀錶盤控制項,使用圓盤面上的指針來顯示一定範圍的值,這種顯示和交互方式,讓數據可 ...
  • 在14,15年間帶領幾個不同的團隊,交付了幾個項目,在這個過程中,雖然幾個項目的業務不一樣,但是很多應用程式架構基礎性的功能卻是大同小異,例如認證、授權、請求驗證、異常處理、DTO、日誌、審計、定時任務、調度、多語言、應用配置管理等等這些功能。但是由於項目受限於進度、資源、團隊成員的背景,在當時卻難 ...
  • 1.業務場景 生產車間中使用的條碼掃描,往往一把掃描槍需要掃描不同的條碼來處理不同的業務邏輯,比如,掃描投入料工位條碼、掃描投入料條碼、掃描產出工裝條碼等,每種類型的條碼位數是不一樣,因此通過條碼長度來進行業務區分。 2.初步設計 面對此場景,能夠想到的最簡單的設計就是使用if...else if. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...