2017/7/29

Xamarin.Forms 教學系列文(二十一)Transforms - 位移 & 放大縮小 & 旋轉


學習目標
  • Translation - 位移
  • Scale - 放大縮小
  • Anchoring - 放大縮小錨定點
  • Rotation - 旋轉
颱風天什麼的在家看原文書打教學最棒了...

顧名思義的,這章節要來介紹 Xamarin.Forms 提供的三種物件變形方式

這三種變形跟以下八個屬性有點關係,型態都是 double:
  • TranslationX
  • TranslationY
  • Scale
  • Rotation
  • RotationX
  • RotationY
  • AnchorX
  • AnchorY

先來介紹 Translation - 位移

Translation - 位移

若程式有使用 StackLayout, Grid, AbsoluteLayout 或是 RelativeLayout 來擺放物件,則這些 Layout 會幫物件 建立位置,讓我們暫稱這些位置為 layout position

而 Translation 做位移時,就是相對於 layout postion 去更改位置,
TranslationX 和 TranslationY,其值正負代表的就是以 layout postion 為中心,要位移的四個象限。

來看範例:
在畫面上放置一個準備移動的 Label,和兩個 Slider 分別控制這 Label 的 X、Y 位置
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TranslationDemo.TranslationDemoPage">

    <StackLayout Padding="20, 10">
        <Frame x:Name="frame"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               OutlineColor="Accent">

            <Label Text="TEXT"
                   FontSize="Large" />
        </Frame>

        <!--綁定 X 位移的 Slider-->
        <Slider x:Name="xSlider"
                Minimum="-200"
                Maximum="200"
                Value="{Binding Source={x:Reference frame},
                                Path=TranslationX}" />

        <Label Text="{Binding Source={x:Reference xSlider},
                              Path=Value,
                              StringFormat='TranslationX = {0:F0}'}"
               HorizontalTextAlignment="Center" />

        <!--綁定 Y 位移的 Slider-->
        <Slider x:Name="ySlider"
                Minimum="-200"
                Maximum="200"
                Value="{Binding Source={x:Reference frame},
                                Path=TranslationY }" />

        <Label Text="{Binding Source={x:Reference ySlider},
                              Path=Value,
                              StringFormat='TranslationY = {0:F0}'}"
               HorizontalTextAlignment="Center" />
    </StackLayout>
</ContentPage>

執行結果:


* Translation 會影響任何 Visual Element 的子元素
* Translation 可以適用於任何 Visual Element,包括 StackLayout、Grid 甚至 Page。
* 原文書 p.708 有一個利用 Translation 製作文字陰影的範例,你可以去看看並試著求出陰影面積

Scale
Xamarin.Forms 在做放大縮小時,並不會真的去更改物件的寬和高,而是針對 rendered 物件的座標去做修改

Scale 的預設值是 1,當設定的值大於 1 時,物件會被放大,反之則縮小。
要注意的是,
若將 Scale 設為 0,此物件會消失於畫面上... 想隱藏物件時可以利用這特性,
若將值設為 負數,則此物件會做 180 度的翻轉

來看範例:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SimpleScaleDemo.SimpleScaleDemoPage">
    
    <StackLayout Padding="20, 10">
        <Frame x:Name="frame"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               OutlineColor="Accent">

            <Label Text="TEXT"
                   FontSize="Large" />
        </Frame>

        <!--綁定 Scale 的 Slider-->
        <Slider x:Name="scaleSlider"
                Minimum="-10"
                Maximum="10"
                Value="{Binding Source={x:Reference frame},
                Path=Scale}" />
        <Label Text="{Binding Source={x:Reference scaleSlider},
                              Path=Value,
                              StringFormat='Scale = {0:F1}'}"
               HorizontalTextAlignment="Center" />
    </StackLayout>
    
</ContentPage>

執行結果:



Anchoring the scale

在用 Scale 放大縮小時,允許你 "釘住" 物件上的某一點,那樣就會往錨釘反方向做變化

舉例來說,當你 "釘住" 物件的左上角並設 Scale 為 1.5 時,物件就會往右下放大 1.5

控制 錨釘點 的屬性就是 AnchorX AnchorY,預設值都是 0.5,代表中心為預設位置

來看範例:
跟上一個範例比多了兩個 Stepper 來控制錨定點
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AnchoredScaleDemo.AnchoredScaleDemoPage">
    
    <StackLayout Padding="20, 10">
        <Frame x:Name="frame"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               OutlineColor="Accent">
            
            <Label Text="TEXT"
                   FontSize="Large" />
        </Frame>

        <Slider x:Name="scaleSlider"
                Minimum="-10"
                Maximum="10"
                Value="{Binding Source={x:Reference frame},
                                Path=Scale}" />

        <Label Text="{Binding Source={x:Reference scaleSlider},
                              Path=Value,
                              StringFormat='Scale = {0:F1}'}"
               HorizontalTextAlignment="Center" />
        
        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center">
            
            <!-- 綁定 AnchorX 的 Stepper-->
            <Stepper x:Name="anchorXStepper"
                     Minimum="-1"
                     Maximum="2"
                     Increment="0.25"
                     Value="{Binding Source={x:Reference frame},
                                     Path=AnchorX}" />
            
            <Label Text="{Binding Source={x:Reference anchorXStepper},
                                  Path=Value,
                                  StringFormat='AnchorX = {0:F2}'}"
                   VerticalOptions="Center"/>
        </StackLayout>
        
        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center">
            
            <!-- 綁定 AnchorY 的 Stepper-->
            <Stepper x:Name="anchorYStepper"
                     Minimum="-1"
                     Maximum="2"
                     Increment="0.25"
                     Value="{Binding Source={x:Reference frame},
                                     Path=AnchorY}" />
            <Label Text="{Binding Source={x:Reference anchorYStepper},
                                  Path=Value,
                                  StringFormat='AnchorY = {0:F2}'}"
                   VerticalOptions="Center"/>
        </StackLayout>
        
    </StackLayout>
</ContentPage>

執行結果:

Rotation

設定 Rotation 為要旋轉的角度值,
在旋轉時,也可以設定 錨定點,讓物件以 錨定點 為中心做旋轉。

來看範例:
其實跟上一個範例差不多,只是變成綁定 Rotation...
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="PlaneRotationDemo.PlaneRotationDemoPage">
    
    <StackLayout Padding="20, 10">
        <Frame x:Name="frame"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               OutlineColor="Accent">
            
            <Label Text="TEXT"
                   FontSize="Large" />
        </Frame>

        <!--控制旋轉角度的 Slider-->
        <Slider x:Name="rotationSlider"
                Maximum="360"
                Value="{Binding Source={x:Reference frame},
                                Path=Rotation}" />
        <Label Text="{Binding Source={x:Reference rotationSlider},
                              Path=Value,
                              StringFormat='Rotation = {0:F0}'}"
               HorizontalTextAlignment="Center" />
        
        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center">
            
            <!--控制 X 錨定點的 Stepper -->
            <Stepper x:Name="anchorXStepper"
                     Minimum="-1"
                     Maximum="2"
                     Increment="0.25"
                     Value="{Binding Source={x:Reference frame},
                                     Path=AnchorX}" />
            
            <Label Text="{Binding Source={x:Reference anchorXStepper},
                Path=Value,
                StringFormat='AnchorX = {0:F2}'}"
                   VerticalOptions="Center"/>
        </StackLayout>
        
        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center">

            <!--控制 Y 錨定點的 Stepper -->
            <Stepper x:Name="anchorYStepper"
                     Minimum="-1"
                     Maximum="2"
                     Increment="0.25"
                     Value="{Binding Source={x:Reference frame},
                     Path=AnchorY}" />
            
            <Label Text="{Binding Source={x:Reference anchorYStepper},
                                  Path=Value,
                                  StringFormat='AnchorY = {0:F2}'}"
                   VerticalOptions="Center"/>
        </StackLayout>
    </StackLayout>
</ContentPage>

執行結果:

本章還有最後兩個屬性,RotationX 和 RotationY,

可以設定物件要在 X 軸或 Y 軸旋轉的角度,這樣就能達到 3D 旋轉的效果~
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ThreeDeeRotationDemo.ThreeDeeRotationDemoPage">
    
    <StackLayout Padding="20, 10">
        <Frame x:Name="frame"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               OutlineColor="Accent">
            
            <Label Text="TEXT"
                   FontSize="72" />
        </Frame>
        
        <!-- 控制錨定 X 軸的 Slidder-->
        <Slider x:Name="rotationXSlider"
                Maximum="360"
                Value="{Binding Source={x:Reference frame},
                                Path=RotationX}" />
        
        <Label Text="{Binding Source={x:Reference rotationXSlider},
                              Path=Value,
                              StringFormat='RotationX = {0:F0}'}"
               HorizontalTextAlignment="Center" />

        <!-- 控制錨定 Y 軸的 Slidder-->
        <Slider x:Name="rotationYSlider"
                Maximum="360"
                Value="{Binding Source={x:Reference frame},
                                Path=RotationY}" />
        
        <Label Text="{Binding Source={x:Reference rotationYSlider},
                              Path=Value,
                              StringFormat='RotationY = {0:F0}'}"
               HorizontalTextAlignment="Center" />
        
        <Slider x:Name="rotationZSlider"
                Maximum="360"
                Value="{Binding Source={x:Reference frame},
                                Path=Rotation}" />
        <Label Text="{Binding Source={x:Reference rotationZSlider},
                              Path=Value,
                              StringFormat='Rotation(Z) = {0:F0}'}"
               HorizontalTextAlignment="Center" />
        
        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center">
            
            <Stepper x:Name="anchorXStepper"
                     Minimum="-1"
                     Maximum="2"
                     Increment="0.25"
                     Value="{Binding Source={x:Reference frame},
                                     Path=AnchorX}" />
            <Label Text="{Binding Source={x:Reference anchorXStepper},
                                  Path=Value,
                                  StringFormat='AnchorX = {0:F2}'}"
                   VerticalOptions="Center"/>
        </StackLayout>
        
        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center">
            
            <Stepper x:Name="anchorYStepper"
                     Minimum="-1"
                     Maximum="2"
                     Increment="0.25"
                     Value="{Binding Source={x:Reference frame},
                                     Path=AnchorY}" />
            <Label Text="{Binding Source={x:Reference anchorYStepper},
                                  Path=Value,
                                  StringFormat='AnchorY = {0:F2}'}"
                   VerticalOptions="Center"/>
        </StackLayout>
    </StackLayout>
</ContentPage>

執行結果:

*其實可以把原本的 Rotation 屬性想成是隨著 Z 軸在做旋轉



沒有留言:

張貼留言