天天看點

第二十一章:變換(六)

兩個按鈕的Clicked處理程式每個都啟動一個獨立的動畫。 第一個Button的Clicked處理程式将其Scale屬性從1設定為5并再次傳回,而第二個Button的Clicked處理程式将其FontSize屬性設定為1到5的比例因子,然後再傳回。

這是關于中途的Scale屬性的動畫:

第二十一章:變換(六)

正如您所看到的,Button的縮放不會考慮螢幕上可能出現的任何其他内容,而在iOS和Windows 10 Mobile螢幕上,您實際上可以通過Button的透明區域看到頂部BoxView元素,而 opaque Android Button完全隐藏了頂級BoxView。 頂部按鈕下面的BoxView實際上位于按鈕的頂部,并且在所有三個平台上都可見。

在三個平台上,FontSize屬性的動畫增加處理方式略有不同:

第二十一章:變換(六)

在iOS上,Button文本在中間被截斷,Button按鈕保持相同的高度。在Android上,Button文本換行,放大的Button将兩個BoxView元素推到一邊。 Windows運作時按鈕也會截斷文本,但方式與iOS不同,與Android一樣,增加的Button高度也會推動兩個BoxView元素。

動畫“縮放”屬性不會影響布局,但動畫化FontSize屬性顯然會影響布局。

ButtonScaler中實作的小動畫系統可以獨立和同時為兩個按鈕設定動畫,但它仍然存在嚴重的缺陷。當該Button正在設定動畫時,嘗試點選按鈕。将為該Button啟動一個新動畫,這兩個動畫将互相幹擾。

有幾種方法可以解決這個問題。一種可能性是将CancellationToken值作為AnimateAndBack方法的參數包含在内,以便可以取消該方法。 (您可以将相同的CancellationToken值傳遞給Task.Delay調用。)這将允許Button的Clicked處理程式在開始新動畫之前取消任何正在進行的動畫。

另一個選項是AnimateAndBack傳回Task對象。這允許按鈕的Clicked處理程式将await運算符與AnimateAndBack一起使用。在AnimateAndBack完成動畫時,Button可以在調用AnimateAndBack之前輕松禁用自身并重新啟用自身。

無論如何,如果您希望通過短暫增加和減少按鈕大小來向使用者實施回報,那麼動畫縮放比使用FontSize更安全,更有效。您将在下一章動畫和第23章“觸發器和行為”中看到其他技術。

Scale屬性的另一個用途是調整元素大小以适合可用空間。 您可能會在第5章“處理大小”結束時回想起FitToSizeClock程式。您可以使用Scale屬性執行非常類似的操作,但不需要進行估計或遞歸計算。

ScaleToSize程式的XAML檔案包含缺少某些文本的标簽,并且還缺少“縮放”設定以使标簽更大:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScaleToSize.ScaleToSizePage"
             SizeChanged="OnSizeChanged">
 
    <Label x:Name="label"
           HorizontalOptions="Center"
           VerticalOptions="Center"
           SizeChanged="OnSizeChanged" />
</ContentPage>           

ContentPage和Label都安裝了SizeChanged處理程式,它們都使用相同的處理程式。 此處理程式隻是将Label的Scale屬性設定為頁面寬度和高度的最小值除以Label的寬度和高度:

public partial class ScaleToSizePage : ContentPage
{
    public ScaleToSizePage()
    {
        InitializeComponent();
        UpdateLoop();
    }
    async void UpdateLoop()
    {
        while (true)
        {
            label.Text = DateTime.Now.ToString("T");
            await Task.Delay(1000);
        }
    }
    void OnSizeChanged(object sender, EventArgs args)
    {
        label.Scale = Math.Min(Width / label.Width, Height / label.Height);
    }
}           

因為設定Scale屬性不會觸發另一個SizeChanged事件,是以不存在觸發無限遞歸循環的危險。 但使用Task.Delay的實際無限循環使Label更新為目前時間:

第二十一章:變換(六)

當然,将手機側向轉動會使标簽更大:

第二十一章:變換(六)

在這裡,您可以檢測到與Android和Windows運作時相比,iOS中Scale屬性的實作略有不同。 在Android和Windows上,生成的文本看起來好像是用大字型繪制的。 但是,iOS螢幕上的文字看起來有點模糊。 當作業系統光栅化預分頻标簽時,會出現這種模糊,這意味着作業系統将其轉換為位圖。 然後根據“比例”設定擴充位圖。

繼續閱讀