入口动画
实际编程中的一种常见类型的动画是在页面首次可见时发生的。 页面上的各种元素可以在进入最终状态之前进行简要动画处理。 这通常被称为入口动画,可能涉及:
- 翻译,将元素移动到最终位置。
- 缩放,将元素放大或缩小到最终尺寸。
- 不透明度的变化,以将元素淡入视图。
- 3D旋转,使整个页面看起来好像一样。
通常,您需要使用这些属性的默认值来停止页面上的元素:TranslationX和TranslationY值为0,Scale和Opacity值为1,所有Rotation属性设置为0。
换句话说,入口动画应该以每个属性的默认值结束,这意味着它们以非默认值开始。 此方法还允许程序稍后将这些元素应用于其他变换而不考虑入口动画。
在XAML中设计布局时,您只需忽略这些动画。 例如,这是一个包含多个元素的页面,仅用于演示目的。 该程序称为FadingEntrance:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FadingEntrance.FadingEntrancePage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10, 20, 10, 10"
Android="10"
WinPhone="10" />
</ContentPage.Padding>
<StackLayout x:Name="stackLayout">
<Label Text="The App"
Style="{DynamicResource TitleStyle}"
FontAttributes="Italic"
HorizontalOptions="Center" />
<Button Text="Countdown"
FontSize="Large"
HorizontalOptions="Center" />
<Label Text="Primary Slider"
HorizontalOptions="Center" />
<Slider Value="0.5" />
<ListView HorizontalOptions="Center"
WidthRequest="200">
<ListView.ItemsSource>
<x:Array Type="{x:Type Color}">
<Color>Red</Color>
<Color>Green</Color>
<Color>Blue</Color>
<Color>Aqua</Color>
<Color>Purple</Color>
<Color>Yellow</Color>
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<BoxView Color="{Binding}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Text="Secondary Slider"
HorizontalOptions="Center" />
<Slider Value="0.5" />
<Button Text="Launch"
FontSize="Large"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
代码隐藏文件会覆盖OnAppearing方法。 在布局页面之后但在页面变为可见之前调用OnAppearing方法。 页面上的所有元素都已调整大小并定位,因此如果您需要获取该信息,则可以在此方法中执行此操作。 在FadingEntrance程序中,OnAppearing覆盖将StackLayout的Opacity属性设置为0(从而使StackLayout中的所有内容都不可见),然后将其设置为1:
public partial class FadingEntrancePage : ContentPage
{
public FadingEntrancePage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
stackLayout.Opacity = 0;
stackLayout.FadeTo(1, 3000);
}
}
这是淡入视图的页面:
我们试试另一个吧。 SlidingEntrance程序中的XAML文件与FadingEntrance相同,但OnAppearing覆盖首先将StackLayout子项的所有TranslationX属性设置为交替值1000和-1000:
public partial class SlidingEntrancePage : ContentPage
{
public SlidingEntrancePage()
{
InitializeComponent();
}
async protected override void OnAppearing()
{
base.OnAppearing();
double offset = 1000;
foreach (View view in stackLayout.Children)
{
view.TranslationX = offset;
offset *= -1;
}
foreach (View view in stackLayout.Children)
{
await Task.WhenAny(view.TranslateTo(0, 0, 1000, Easing.SpringOut),
Task.Delay(100));
}
}
}
然后,第二个foreach循环将这些子动画恢复为TranslationX和TranslationY的默认设置。 但是,动画是交错和重叠的。 方法如下:对Task.WhenAny的第一次调用启动第一个TranslateTo动画,该动画在一秒钟后完成。 但是,Task.WhenAny的第二个参数是Task.Delay,它在十分之一秒内完成,而且当Task.WhenAny也完成时。 foreach循环获取下一个子节点,然后开始它自己的一秒动画。 每个动画在前一个动画之后的十分之一秒开始。
这是过程中的结果:
TranslateTo调用使用Easing.SpringOut函数,这意味着每个动画元素应超过其目标,然后向后移动以在页面中心静止。 但是,你不会看到这种情况发生。 正如您已经发现的那样,当缓动函数的输出超过1时,TranslateTo方法停止工作。
你会看到这个的解决方案 - 以及这个程序的一个版本,其中的元素会超出目的地 - 本章稍后。
最后,这是一个SwingingEntrance动画:
public partial class SwingingEntrancePage : ContentPage
{
public SwingingEntrancePage()
{
InitializeComponent();
}
async protected override void OnAppearing()
{
base.OnAppearing();
stackLayout.AnchorX = 0;
stackLayout.RotationY = 180;
await stackLayout.RotateYTo(0, 1000, Easing.CubicOut);
stackLayout.AnchorX = 0.5;
}
}
RotateYTo方法将整个StackLayout及其子项绕Y轴旋转180度到0度。 当AnchorX设置为0时,旋转实际上是在StackLayout的左边缘附近。 在RotationY值小于90度之前,StackLayout将不可见,但如果在页面实际可见之前旋转开始,结果看起来会好一些。 CubicOut缓动功能会使动画在接近完成时减速。 这里正在进行中:
动画完成后,OnAppearing方法将AnchorX返回到其原始值,以便一切都具有程序可能要实现的任何未来动画的默认值。