第二十一章:變換(四)
跳躍和動畫
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提供的動畫系統,有時候自己動手也很有用。
相關文章
- 【odoo14】第二十一章、效能優化Odoo優化
- 《Real-Time Rendering》第四章:變換
- RxJava 原始碼分析系列(四) -操作符變換原理RxJava原始碼
- Hough變換
- z 變換
- 計算機圖形學 第四章 圖形變換計算機
- 仿射變換及其變換矩陣的理解矩陣
- 第四個OpenGL程式,vector 向量 (矩陣變換之 旋轉,縮放)矩陣
- OpenCV計算機視覺學習(3)——影像灰度線性變換與非線性變換(對數變換,伽馬變換)OpenCV計算機視覺
- Z變換(2020.10.21)
- 頻域變換
- 小波變換與傅立葉變換的區別
- 灰度變換函式:對數及對比度拉伸變換函式
- postman(四):新增變數Postman變數
- pose座標變換
- 傅立葉變換
- 貝葉斯變換
- NOIP 2002 字串變換字串
- 各種Fourier變換
- 2D變換
- PL/SQL第一章--概述及變數型別SQL變數型別
- 複變函式與積分變換函式
- 《DNK210使用指南 -CanMV版 V1.0》第二十一章 machine.UART類實驗Mac
- 四元數在旋轉變換和插值中的有趣的視覺化解釋視覺化
- 離散傅立葉變換(DFT)和快速傅立葉變換(FFT)FFT
- 四:java常量和變數Java變數
- OpenGL 使用矩陣變換改變檢視矩陣
- 影像尺寸變換scalepadding方法padding
- 基向量 變換矩陣矩陣
- 快速傅立葉變換
- css32d變換CSSS3
- 變數型別轉換變數型別
- 動詞て型變換
- iOS 仿射變換(CGAffineTransform)iOSORM
- 交換兩個變數變數
- SVG animateTransform變換動畫SVGORM動畫
- 【OpenCV-Python】:影像的傅立葉變換與逆傅立葉變換OpenCVPython
- Python 實現影像快速傅立葉變換和離散餘弦變換Python