问题描述
我正在尝试制作从中心到其他视图边缘的水平填充动画。
首先,我将执行展开动画的视图集中在主视图的中心,然后使用 ScaleXTo
设置主视图宽度的动画:
XAML 代码:
<StackLayout Padding="16" Spacing="10">
<Grid
Margin="0,16">
<BoxView
x:Name="firstView"
BackgroundColor="Blue"
HorizontalOptions="Start"
HeightRequest="30"
WidthRequest="180" />
<BoxView
x:Name="secondView"
BackgroundColor="Black"
HeightRequest="10"
Scale="1"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
WidthRequest="1" />
</Grid>
<Button
Clicked="Button_OnClicked"
Text="Animate!" />
</StackLayout>
背后的代码:
private void Button_OnClicked(object sender,EventArgs e) {
secondView.TranslationX = firstView.Bounds.Center.X;
secondView.ScaleXTo(firstView.Width);
}
执行时,动画视图变得比主视图大,如下图所示
解决方法
更新:既然您在评论中解释说您希望动画从中心开始,我正在更新答案。 看起来 Xamarin 中存在缩放错误,因为对于 WidthRequest 和 ScaleX 的某些值,它按预期工作。例如,此实现可以为您解决问题:
private void Button_OnClicked(object sender,EventArgs e)
{
double scale = 6;
double startWidth = firstView.Width / scale;
secondView.TranslationX = firstView.Bounds.Center.X - startWidth / 2;
secondView.WidthRequest = startWidth;
secondView.ScaleXTo(scale,1000);
}
但它不适用于更大的 scale
值,即。它将超出 firstView
。
因此,最好采用类似 @Cfun 的提议。他的解决方案唯一的问题是它会将 secondView
扩展到整个 firstView
。另外,我正在使用 Task
,因为您的 Button_OnClicked
不是 async
方法:
private void Button_OnClicked(object sender,EventArgs e)
{
var rectangle = new Rectangle(secondView.X,secondView.Y,firstView.Width,secondView.Height);
secondView.TranslationX = firstView.Bounds.Center.X;
Task translate = Task.Factory.StartNew(() => secondView.TranslateTo(rectangle.Left,500));
Task layout = Task.Factory.StartNew(() => secondView.LayoutTo(rectangle,500));
Task.WaitAll(new[] { translate,layout });
}
旧答案:
如果您只想实现水平填充,则无需平移然后缩放。您可以像这样实现 Button_OnClicked
:
private void Button_OnClicked(object sender,EventArgs e)
{
secondView.LayoutTo(new Rectangle(secondView.X,secondView.Height));
}
,
您可以通过同时运行两个动画来实现它,以获得平滑的视觉、平移和大小调整 (LayoutTo
)
private async void Button_Clicked(object sender,EventArgs e)
{
secondView.TranslationX = firstView.Bounds.Center.X;
secondView.TranslateTo(firstView.Bounds.Left,500);
await secondView.LayoutTo(firstView.Bounds,500);
}