天天看點

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

在Windows 10 UWP界面實作的過程中,有時會遇到一些重複性的、靜态的界面設計。比如:畫許多等距的線條,畫一圈時鐘型的刻度線,同特别的政策排布元素,等等。

讀者可能覺得這些需求十分簡單,馬上就想到了通過for循環之類來實作。隻需要在Loaded事件裡添上這些元素就好了。

但這樣可能存在一些問題——如果這些UI元素隻是靜态的,是裝飾性的——雖然code-behind不用白不用,但為了這些純靜态元素将代碼邏輯變得臃腫似乎略有不妥。

我們将就這些問題為讀者們介紹一些重複性的靜态界面繪制小技巧。

Windows.UI.Xaml.Shapes.Shape基類,以及繼承自它的Ellipse、Line、Path、Rectangle等類,都具有一些Stroke****之名的屬性,可以實作描邊效果。其中有一個比較特别的StrokeDashArray屬性,它能實作虛線型的描邊效果,加以擴充的話是我們實作重複性UI繪制的好幫手。

在XAML中,這一屬性表現為形如”1,2,3,4”的字元串格式,而本質上它是一個DoubleCollection。其中的數值兩兩配對,依次表示虛線的短劃線和空白間隔的長度,并且能周期性地出現。如果數值個數隻有奇數個,那麼比對不滿的那一組中,空白間隔的長度将和短劃線的長度一緻。

PS:關于這一屬性的具體文法,UWP MSDN[1]沒有很詳細的描述。不過舊版本的API MSDN[2]中有對其文法的接受,這部分内容可以參考舊版本的頁面。

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

可以看到構成了短劃線和空白間隔長度依次為1,2,3,4的虛線。這裡是指的機關長度,和StrokeThickness屬性有關,該屬性的值會被作為機關長度。而Line長度為400,故可以看到虛線按設定形成了8段。

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

現在短劃線和間隔的長度都是0.1機關長度,而目前的機關長度是50(也導緻線段寬度更大,現在看起來像是并列的豎線了)。

我們還可以算出虛線段的數量為: 400 ÷((0.1+0.1) × 50) =40 段。

靈活運用這種方式,可以在XAML裡直接畫出一些重複的UI元素了,比如這樣:

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

這裡Line是呈45°的,并将它的描邊寬度設的很大(超過400*400矩形的對角線長度),并用Clip限定400*200矩形範圍。

其中還用到了StrokeDashOffset屬性來設定StrokeDashArray的初始偏移量,這裡也是指機關長度。

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

這段XAML中設定的StrokeDashArray="61.89,1000"可能很讓人摸不着頭腦。

我們可以看出這個圓形長寬都是200,周長最多不過600多,我們将代表空白部分的值設定為1000(遠大于200π),用于将進度條未滿的部分全部作為空白部分,隐藏掉。

至于前面一個數值是如何計算的,過程比較複雜:

首先要考慮的是圓的周長,但這是否是上面說的200π呢?實際上不是。200是來自于我們在XAML裡設定的Width和Height,但Stroke在計算時采用的是ActualWidth和ActualHeight,這裡可以了解為Shape控件的中心線段,即是我們在XAML設計器裡選中一個Shape控件後可以看見的這條線(箭頭所指):

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

是以這裡的ActualWidth = Width – StrokeThickness = 200 - 3 = 197。

再以此計算30%進度條的長度為:197π × 30% ÷ 3 = 61.889(不要忘了除以機關長度~)。

需要畫出精準的時鐘刻度,一圈分針一圈時針:

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

大家注意到了這段XAML中應用了一個自定義的IValueConverter——CircleStrokeDashArrayConverter。此類源碼如下:

使用時我們需要在Binding中将Ellipse本身傳入converter。Converter從Ellipse的屬性設定中擷取資訊完成StrokeDashArray的構造(注意StrokeDashArray屬性的Binding要寫在最後,這樣才能擷取到正确的值),StrokeDashOffset導緻的偏移是和Shape線條的方向相反的,我們用它來設定每段短劃線的長度。并配合ConverterParameter(設定分段數)達到複用性。

PS:隻能用于正圓。橢圓的周長無法簡單計算。其他的Shape就更不适用了。

對于這些無法計算path長度的Shape,需要自己調整和估計其長度。

StrokeDashArray畫出的線段,在分段處的切口是和中心線段的切線垂直的(平行法線方向)。直覺印象如下:

Win10 UWP開發中的重複性靜态UI繪制小技巧 1介紹Shape.StrokeDashArray屬性不過StrokeDashArray的使用還有一個小問題參考

(此為“坐和放寬”進度條終點處放大圖)

可以想象,包括我們畫出的鐘盤也是這種情況,每一個刻度并不是一道“線段”,而是一個小小的“扇形”,雖然在視覺上并不明顯。

其實這并不是什麼嚴重的問題啦,當然有時會的确不能符合需求。就此我們将在另一篇博文中介紹更完善、更适用的解決方案。

繼續閱讀