规模变换
VisualElement类定义名为Scale的属性,您可以使用该属性更改元素的呈现大小。 Scale属性不会影响布局(将在ButtonScaler程序中演示)。它不会影响元素的get-only Width和Height属性,也不会影响包含Width和Height值的get-only Bounds属性。对Scale属性的更改不会导致触发SizeChanged事件。
缩放影响渲染视觉元素的坐标,但与TranslationX和TranslationY的方式完全不同。两个转换属性将值添加到坐标,而Scale属性是乘法。 Scale的默认值为1.大于1的值会增加元素的大小。例如,值3使元素的大小为正常大小的三倍。小于1的值会减小尺寸。 Scale值为0是合法的,但会导致元素不可见。如果您正在使用Scale并且您的元素似乎已经消失,请检查它是否以某种方式获得Scale值为0。
小于0的值也是合法的,并且除了改变尺寸之外,还使元件旋转180度。
您可以使用SimpleScaleDemo程序试验缩放设置。 (该程序有一个简单的前缀,因为它不包括AnchorX和AnchorY属性的影响,这将很快讨论。)XAML类似于TranslationDemo程序:
<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>
<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>
这是在行动。 请注意Android手机上的负面比例设置:
在Windows 10移动显示器上,框架已缩放到如此大,以至于您无法看到其左侧和右侧。
在现实生活中,您可能希望使用“缩放”在单击“按钮”时向用户提供一些反馈。 按钮可以短暂地扩大尺寸并再次恢复正常。 但是,Scale不是更改Button大小的唯一方法。 您还可以通过增加和减少FontSize属性来更改Button大小。 但是,这两种技术非常不同:Scale属性不会影响布局,但FontSize属性会影响布局。
ButtonScaler程序说明了这种差异。 XAML文件由两个夹在两对BoxView元素之间的Button元素组成:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonScaler.ButtonScalerPage">
<StackLayout>
<!-- "Animate Scale" Button between two BoxViews. -->
<BoxView Color="Accent"
HeightRequest="4"
VerticalOptions="EndAndExpand" />
<Button Text="Animate Scale"
FontSize="Large"
BorderWidth="1"
HorizontalOptions="Center"
Clicked="OnAnimateScaleClicked" />
<BoxView Color="Accent"
HeightRequest="4"
VerticalOptions="StartAndExpand" />
<!-- "Animate FontSize" Button between two BoxViews. -->
<BoxView Color="Accent"
HeightRequest="4"
VerticalOptions="EndAndExpand" />
<Button Text="Animate FontSize"
FontSize="Large"
BorderWidth="1"
HorizontalOptions="Center"
Clicked="OnAnimateFontSizeClicked" />
<BoxView Color="Accent"
HeightRequest="4"
VerticalOptions="StartAndExpand" />
</StackLayout>
</ContentPage>
这是页面通常的样子:
代码隐藏文件实现了一种有点通用的动画方法。 在某种意义上,它是通用的,参数包括两个值,表示动画的起始值和结束值。 这两个值通常称为从值和值到值。 动画参数还包括动画的持续时间和回调方法。 回调方法的参数是“from”值和“to”值之间的值,并且调用方法可以使用该值来执行实现动画所需的任何操作。
但是,这种动画方法并不完全一般化。 它实际上在动画的前半部分计算从值到值的值,然后在动画的后半部分计算从值到值的值。 这有时被称为倒车动画。
该方法称为AnimateAndBack,它使用Task.Delay调用来调整动画,并使用.NET Stopwach对象来确定已用时间:
public partial class ButtonScalerPage : ContentPage
{
public ButtonScalerPage()
{
InitializeComponent();
}
void OnAnimateScaleClicked(object sender, EventArgs args)
{
Button button = (Button)sender;
AnimateAndBack(1, 5, TimeSpan.FromSeconds(3), (double value) =>
{
button.Scale = value;
});
}
void OnAnimateFontSizeClicked(object sender, EventArgs args)
{
Button button = (Button)sender;
AnimateAndBack(button.FontSize, 5 * button.FontSize,
TimeSpan.FromSeconds(3), (double value) =>
{
button.FontSize = value;
});
}
async void AnimateAndBack(double fromValue, double toValue,
TimeSpan duration, Action<double> callback)
{
Stopwatch stopWatch = new Stopwatch();
double t = 0;
stopWatch.Start();
while (t < 1)
{
double tReversing = 2 * (t < 0.5 ? t : 1 - t);
callback(fromValue + (toValue - fromValue) * tReversing);
await Task.Delay(16);
t = stopWatch.ElapsedMilliseconds / duration.TotalMilliseconds;
}
stopWatch.Stop();
callback(fromValue);
}
}