我试图在Xamarin.Forms中创建一个从页面顶部开始动画的通知。我非常接近,但在我在页面上设置动画之前,我无法获得ContentView的高度。我已经制作了一个xamarin workbook来演示我的问题,可以在android模拟器上运行。 (猜测它可以在ios / wpf上进行一些修改)
The workbook is available here
问题出在cut :: [[a]] -> [[a]]
cut = map (\xs -> drop ((min(length xs)) - length xs) xs)
,我首先将整个内容视图的可见性设置为可见(红色背景)。绿色通知会立即呈现在其最终位置,尽管在设置动画之前设置它在屏幕外的位置的尝试不同。这仅在第一次在页面上动画通知时发生,因为在屏幕上显示动画并再次隐藏后,它的高度可用。
我可以通过将高度偏移硬编码为50来解决这个问题,但为了实现可变高度的一致动画,这并不是要削减它。我还可以创建一个计算行数的方法,然后根据它来动态设置高度,但我希望有一种实际渲染方法,并以某种方式得到组件的实际高度,而不会让用户看到它直到我从我想要的地方开始动画。
ToastNotificationView.AnimateIn()
在InitializeComponent方法中创建布局以支持xamarin工作簿。这可能是出于此问题的目的。
public class ToastNotificationView: ContentView {
// The notification item to be animated in/out
private StackLayout MainStackLayout;
public ToastNotificationView() {
InitializeComponent(); // Let's pretend workbooks supports xaml
//Subscribing to notification events
NotificationService.NotificationAppearing += AnimateIn;
// TODO: Find out how to unsubscribe in contentview without access to life cycle hooks
}
private async void OnDismissClicked(object sender, EventArgs e) {
await AnimateOut();
}
private async Task AnimateOut() {
await MainStackLayout.TranslateTo(0, -MainStackLayout.Height, 1000);
IsVisible = false;
}
private async void AnimateIn(object sender, EventArgs e) {
// Make the entire view visible
IsVisible = true;
// First time, height is always zero, so we can't set it like this
MainStackLayout.TranslationY = -MainStackLayout.Height;
// Attempting to await a 1ms animation to get a height does not result in correct height either
await MainStackLayout.TranslateTo(0, 0, 1);
await MainStackLayout.TranslateTo(0, -MainStackLayout.Height, 1);
//Still does not animate in on initial animation
await MainStackLayout.TranslateTo(0, 0, 1000);
}
}
答案 0 :(得分:1)
您可以使用Measure
获取身高:
private async void AnimateIn(object sender, EventArgs e)
{
var parent = (VisualElement)Parent;
SizeRequest sizeRequest = MainStackLayout.Measure(parent.Width, parent.Height);
MainStackLayout.TranslationY = -sizeRequest.Request.Height;
IsVisible = true;
await MainStackLayout.TranslateTo(0, 0, 1000);
}