第二十一章:变换(四)

简介: 跳跃和动画ButtonJump程序主要用于演示无论您使用翻译在屏幕上移动按钮的位置,Button都会以正常方式响应按键。 XAML文件将Button放在页面中间(减去顶部的iOS填充):<ContentPage xmlns="http://xamarin.

跳跃和动画
ButtonJump程序主要用于演示无论您使用翻译在屏幕上移动按钮的位置,Button都会以正常方式响应按键。 XAML文件将Button放在页面中间(减去顶部的iOS填充):

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonJump.ButtonJumpPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="0, 20, 0, 0" />
    </ContentPage.Padding>
    <ContentView>
        <Button Text="Tap me!"
                FontSize="Large"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="OnButtonClicked" />
    </ContentView>
</ContentPage>

对于每次调用OnButtonClicked处理程序,代码隐藏文件将TranslationX和TranslationY属性设置为新值。 新值随机计算但受限制,以便Button始终保持在屏幕边缘:

public partial class ButtonJumpPage : ContentPage
{
    Random random = new Random();
    public ButtonJumpPage()
    {
        InitializeComponent();
    }
    void OnButtonClicked(object sender, EventArgs args)
    {
        Button button = (Button)sender;
        View container = (View)button.Parent;
        button.TranslationX = (random.NextDouble() - 0.5) * (container.Width - button.Width);
        button.TranslationY = (random.NextDouble() - 0.5) * (container.Height - button.Height);
    }
}

例如,如果Button的宽度为80个单位,而ContentView的宽度为320个单位,则差异为240个单位,当Button位于ContentView的中心时,Button的每一侧为120个单位。 Random的NextDouble方法返回0到1之间的数字,减去0.5会产生介于-0.5和0.5之间的数字,这意味着TranslationX被设置为介于-120和120之间的随机值。这些值可能将Button定位到屏幕的边缘,但没有超越。
请记住,TranslationX和TranslationY是属性而不是方法。它们不是累积的。如果将TranslationX设置为100然后设置为200,则视觉元素不会从其布局位置偏移总共300个单位。第二个TranslationX值200替换而不是添加到初始值100。
使用ButtonJump程序几秒钟可能会引发一个问题:这可以动画吗? Button可以滑向新点而不是简单地跳到那里吗?
当然。有几种方法可以做,包括下一章讨论的Xamarin.Forms动画方法。 ButtonGlide程序中的XAML文件与ButtonJump中的XAML文件相同,只是Button现在有一个名称,以便程序可以在Clicked处理程序之外轻松引用它:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonGlide.ButtonGlidePage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="0, 20, 0, 0" />
    </ContentPage.Padding>
    <ContentView>
        <Button x:Name="button"
                Text="Tap me!"
                FontSize="Large"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="OnButtonClicked" />
    </ContentView>
</ContentPage>

代码隐藏文件通过将几个基本信息保存为字段来处理按钮单击:指示从TranslationX和TranslationY的当前值获得的起始位置的点; 通过从随机目的地点减去该起点计算的矢量(也是点值); 和单击按钮时的当前DateTime:

public partial class ButtonGlidePage : ContentPage
{
    static readonly TimeSpan duration = TimeSpan.FromSeconds(1);
    Random random = new Random();
    Point startPoint;
    Point animationVector;
    DateTime startTime;
    public ButtonGlidePage()
    {
        InitializeComponent();
        Device.StartTimer(TimeSpan.FromMilliseconds(16), OnTimerTick);
    }
    void OnButtonClicked(object sender, EventArgs args)
    {
        Button button = (Button)sender;
        View container = (View)button.Parent;
        // The start of the animation is the current Translation properties.
        startPoint = new Point(button.TranslationX, button.TranslationY);
 
        // The end of the animation is a random point.
        double endX = (random.NextDouble() - 0.5) * (container.Width - button.Width);
        double endY = (random.NextDouble() - 0.5) * (container.Height - button.Height);
        // Create a vector from start point to end point.
        animationVector = new Point(endX - startPoint.X, endY - startPoint.Y);
        // Save the animation start time.
        startTime = DateTime.Now;
    }
    bool OnTimerTick()
    {
        // Get the elapsed time from the beginning of the animation.
        TimeSpan elapsedTime = DateTime.Now - startTime;
        // Normalize the elapsed time from 0 to 1.
        double t = Math.Max(0, Math.Min(1, elapsedTime.TotalMilliseconds / 
                                                duration.TotalMilliseconds));
        // Calculate the new translation based on the animation vector.
        button.TranslationX = startPoint.X + t * animationVector.X;
        button.TranslationY = startPoint.Y + t * animationVector.Y;
        return true;
    }
}

每16毫秒调用一次定时器回调。那不是一个随意的数字!视频显示器的硬件刷新率通常为每秒60次。因此,每帧都有效约16毫秒。以此速率播放动画是最佳选择。每16毫秒一次,回调计算从动画开始经过的时间,并将其除以持续时间。这是一个通常称为t(时间)的值,在动画过程中范围从0到1。此值乘以向量,结果将添加到startPoint。这是TranslationX和TranslationY的新价值。
虽然在应用程序运行时会连续调用计时器回调,但是当动画完成时,TranslationX和TranslationY属性将保持不变。但是,您不必等到Button停止移动才能再次点击它。 (您需要快速,或者您可以将持续时间属性更改为更长的时间。)新动画从Button的当前位置开始,并完全替换上一个动画。
计算t的归一化值的一个优点是,修改该值变得相当容易,因此动画不具有恒定的速度。例如,尝试在初始计算t之后添加此语句:

t = Math.Sin(t * Math.PI / 2);

当动画开始时t的原始值为0时,Math.Sin的参数为0,结果为0.当t的原始值为1时,Math.Sin的参数为π/ 2,并且 结果是1.但是,这两点之间的值不是线性的。 当t的初始值为0.5时,该语句将t重新计算为45度的正弦值,即0.707。 因此,当动画结束一半时,Button已经将70%的距离移动到目的地。 总的来说,你会看到一个动画在开始时更快,到最后更慢。
在本章中,您将看到几种不同的动画方法。 即使您已经熟悉Xamarin.Forms提供的动画系统,有时候自己动手也很有用。

目录
相关文章
|
11月前
|
编解码 缓存 计算机视觉
神还原物体复杂、高频细节,4K-NeRF高保真视图合成来了
神还原物体复杂、高频细节,4K-NeRF高保真视图合成来了
|
机器学习/深度学习 人工智能 编解码
CVPR 2022 | 逆渲染中的⾼效间接光照建模
CVPR 2022 | 逆渲染中的⾼效间接光照建模
470 0
CVPR 2022 | 逆渲染中的⾼效间接光照建模
Halcon标定系列(5):4点标定之眼在手外项目实践,已知仿射变换矩阵,计算得到旋转角度和缩放因子等参数
Halcon标定系列(5):4点标定之眼在手外项目实践,已知仿射变换矩阵,计算得到旋转角度和缩放因子等参数
807 0
Halcon标定系列(5):4点标定之眼在手外项目实践,已知仿射变换矩阵,计算得到旋转角度和缩放因子等参数
|
Android开发 索引
第二十一章:变换(十)
样式通过将AnchorX值设置为0来结束,该值将旋转中心设置为每个Label的左边缘的垂直中心。 然后每个Label都会获得一个独特的旋转设置:显然,选择“ROTATE”字符串之前的空格,以便R的垂直条组合形成一个看起来几乎像圆的16边多边形。
1019 0
|
JavaScript Android开发 索引
第二十一章:变换(九)
旋转的文字效果轮换很有趣。 旋转动画时更有趣(正如您将在下一章中看到的那样),但即使使用静态图像也很有趣。本章和下一章中的几个旋转示例涉及将视觉元素排列在一个圆圈中,所以让我们首先尝试显示一个简单的圆圈。
841 0
|
Android开发
第二十一章:变换(八)
旋转变换 “旋转”属性旋转屏幕表面上的可视元素。 将“旋转”属性设置为以度为单位的角度(不是弧度)。 正角度顺时针旋转元素。 您可以将“旋转”设置为小于0或大于360的角度。实际旋转角度是旋转属性模数360的值。
818 0
|
Android开发
第二十一章:变换(十四)
3D-ish旋转 即使计算机屏幕是平面和二维的,也可以在这些屏幕上绘制视觉对象,使其具有第三维的外观。 在本章的前面,您看到了一些文本效果,它们提供了第三个维度的提示,而Xamarin.Forms支持两个额外的旋转,名为RotationX和RotationY,它们似乎也突破了屏幕固有的二维平面度。
1344 0
|
Android开发 iOS开发
第二十一章:变换(七)
锚定规模当你尝试使用Scale属性时,你可能已经注意到视觉元素的任何扩展都是从元素的中心向外发生的,如果你将视觉元素缩小到任何东西,它也会向中心收缩。这是另一种思考方式:无论Scale属性的设置如何,视觉元素正中心的点都保持在同一位置。
935 0
|
Android开发 iOS开发 Windows
第二十一章:变换(六)
两个按钮的Clicked处理程序每个都启动一个独立的动画。 第一个Button的Clicked处理程序将其Scale属性从1设置为5并再次返回,而第二个Button的Clicked处理程序将其FontSize属性设置为1到5的比例因子,然后再返回。
940 0
|
JavaScript Android开发
第二十一章:变换(五)
规模变换 VisualElement类定义名为Scale的属性,您可以使用该属性更改元素的呈现大小。 Scale属性不会影响布局(将在ButtonScaler程序中演示)。它不会影响元素的get-only Width和Height属性,也不会影响包含Width和Height值的get-only Bounds属性。
906 0

热门文章

最新文章