This commit is contained in:
Javier Suárez Ruiz 2022-05-01 17:03:22 +02:00
Родитель 616581c21f
Коммит db84daa3b7
72 изменённых файлов: 3632 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,14 @@
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiAnimation.Sample"
x:Class="MauiAnimation.Sample.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,12 @@
namespace MauiAnimation.Sample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
}

Просмотреть файл

@ -0,0 +1,817 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiAnimation.Sample.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiAnimation.Sample"
xmlns:mauianimation="clr-namespace:MauiAnimation;assembly=MauiAnimation"
Title="MauiAnimation">
<Shell.Resources>
<ResourceDictionary>
<Style x:Key="TitleStyle" TargetType="Label">
<Setter Property="Visual" Value="Material" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Margin" Value="12" />
</Style>
<Style TargetType="Button">
<Setter Property="Visual" Value="Material" />
<Setter Property="WidthRequest" Value="100" />
</Style>
<mauianimation:BounceInAnimation
x:Key="BounceInAnimation"
Target="{x:Reference BounceBox}"
Duration="500"/>
<mauianimation:BounceOutAnimation
x:Key="BounceOutAnimation"
Target="{x:Reference BounceBox}"
Duration="250"/>
<mauianimation:FadeToAnimation
x:Key="FadeToAnimation"
Target="{x:Reference FadeBox}"
Duration="2000"
Opacity="0"/>
<mauianimation:FlipAnimation
x:Key="FlipAnimation"
Target="{x:Reference FlipBox}"
Duration="250"/>
<mauianimation:RotateToAnimation
x:Key="RotateToAnimation"
Target="{x:Reference RotateBox}"
Duration="750"
Rotation="360"/>
<mauianimation:ScaleToAnimation
x:Key="ScaleToAnimation"
Target="{x:Reference ScaleBox}"
Scale="2"/>
<mauianimation:TranslateToAnimation
x:Key="TranslateToAnimation"
Target="{x:Reference TranslateBox}"
TranslateX="200"
TranslateY="150"/>
<mauianimation:TurnstileInAnimation
x:Key="TurnstileInAnimation"
Target="{x:Reference TurnstileBox}"
Duration="300"/>
<mauianimation:TurnstileOutAnimation
x:Key="TurnstileOutAnimation"
Target="{x:Reference TurnstileBox}"
Duration="150"/>
<mauianimation:ShakeAnimation
x:Key="ShakeAnimation"
Target="{x:Reference ShakeBox}"/>
<mauianimation:HeartAnimation
x:Key="HeartAnimation"
Target="{x:Reference Heart}"/>
<mauianimation:JumpAnimation
x:Key="JumpAnimation"
Target="{x:Reference JumpBox}"
Duration="1500"/>
<Color x:Key="ToColor">#FF0000</Color>
<mauianimation:ColorAnimation
x:Key="ColorAnimation"
Target="{x:Reference ColorBox}"
ToColor="{StaticResource ToColor}"
Duration="1500"/>
<mauianimation:StoryBoard
x:Key="StoryBoard"
Target="{x:Reference StoryBoardBox}">
<mauianimation:ScaleToAnimation Scale="2"/>
<mauianimation:ShakeAnimation />
</mauianimation:StoryBoard>
<mauianimation:RotateToAnimation
x:Key="DelayedAnimation"
Target="{x:Reference DelayedAnimationBox}"
Duration="750"
Rotation="360"
Delay="2000"/>
<mauianimation:RelRotateToAnimation
x:Key="ForeverAnimation"
Target="{x:Reference ForeverAnimationBox}"
Easing="Linear"
Duration="1000"
Rotation="360"
RepeatForever="True"/>
</ResourceDictionary>
</Shell.Resources>
<TabBar>
<!-- BASIC ANIMATIONS -->
<Tab
Title="Animations">
<ShellContent>
<ContentPage
Title="Basic Animations">
<ScrollView>
<StackLayout>
<!-- BOUNCE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Bounce"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="BounceBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Red" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Bounce In">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource BounceInAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- FADE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Fade"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="FadeBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Blue" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Fade">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource FadeToAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- FLIP -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Flip"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="FlipBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Olive" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Flip">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource FlipAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- ROTATE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Rotate"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="RotateBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Teal" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Rotate">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource RotateToAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- SCALE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Scale"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="ScaleBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Fuchsia" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Scale">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource ScaleToAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- TRANSLATE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Translate"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="TranslateBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Purple" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Translate">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource TranslateToAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- TURNSTILE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Turnstile"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="TurnstileBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Lime" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Turnstile Out">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource TurnstileOutAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- SHAKE -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Shake"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="ShakeBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Silver" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Shake">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource ShakeAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- BREATHING -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Breathing"
Style="{StaticResource TitleStyle}"/>
<Image
Grid.Row="1"
x:Name="Heart"
Source="heart.png"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"/>
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Breath">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource HeartAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- JUMP -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Jump"
Style="{StaticResource TitleStyle}"/>
<BoxView
Grid.Row="1"
x:Name="JumpBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Aqua" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Jump">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource JumpAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<!-- COLOR -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Text="Color"
Style="{StaticResource TitleStyle}"/>
<Grid
Grid.Row="1"
x:Name="ColorBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
BackgroundColor="Green" />
<Button
Grid.Row="2"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Color">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource ColorAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</StackLayout>
</ScrollView>
</ContentPage>
</ShellContent>
</Tab>
<!-- STORYBOARD -->
<Tab
Title="Storyboards">
<ShellContent>
<ContentPage
Title="StoryBoards">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<BoxView
Grid.Row="0"
x:Name="StoryBoardBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Silver" />
<Button
Grid.Row="1"
HorizontalOptions="Center"
VerticalOptions="End"
Text="StoryBoard">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource StoryBoard}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</ContentPage>
</ShellContent>
</Tab>
<!-- ANIMATION EXTENSIONS -->
<Tab
Title="Extensions">
<ShellContent>
<ContentPage
Title="Animation Extensions">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<BoxView
Grid.Row="0"
x:Name="AnimationBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Silver" />
<Button
x:Name="AnimationExtensionButton"
Grid.Row="1"
HorizontalOptions="Center"
VerticalOptions="End"
Text="Animate" />
</Grid>
</ContentPage>
</ShellContent>
</Tab>
<!-- DELAYED ANIMATIONS -->
<Tab
Title="Delay">
<ShellContent>
<ContentPage
Title="Delayed Animations">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<BoxView
Grid.Row="0"
x:Name="DelayedAnimationBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Orange" />
<Button
x:Name="DelayedAnimationButton"
Grid.Row="1"
HorizontalOptions="Center"
VerticalOptions="End"
WidthRequest="150"
Text="Animate after 2s">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource DelayedAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</ContentPage>
</ShellContent>
</Tab>
<!-- REPEAT ANIMATIONS -->
<Tab
Title="Repeat">
<ShellContent>
<ContentPage
Title="Repeat Forever Animations">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<BoxView
Grid.Row="0"
x:Name="ForeverAnimationBox"
HorizontalOptions="Center"
VerticalOptions="Center"
HeightRequest="120"
WidthRequest="120"
Color="Green" />
<StackLayout
Grid.Row="1"
Orientation="Horizontal"
HorizontalOptions="Center"
VerticalOptions="End">
<Button
Text="Start">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:BeginAnimation
Animation="{StaticResource ForeverAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
<Button
Text="Stop">
<Button.Triggers>
<EventTrigger Event="Clicked">
<mauianimation:EndAnimation
Animation="{StaticResource ForeverAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</Grid>
</ContentPage>
</ShellContent>
</Tab>
<!-- TRIGGERS -->
<Tab
Title="Triggers">
<ShellContent>
<ContentPage
Title="More Triggers">
<StackLayout>
<Label
Text="Animate Double and Color"/>
<Entry
FontSize="16"
BackgroundColor="LightGray">
<Entry.Triggers>
<Trigger TargetType="Entry" Property="IsFocused" Value="True">
<Trigger.EnterActions>
<mauianimation:AnimateDouble TargetProperty="Entry.FontSize" To="24"/>
<mauianimation:AnimateColor TargetProperty="Entry.TextColor" To="Red"/>
<mauianimation:AnimateColor TargetProperty="VisualElement.BackgroundColor" To="Yellow" Delay="1000"/>
<mauianimation:AnimateDouble TargetProperty="VisualElement.Rotation" To="12" Duration="100"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<mauianimation:AnimateDouble TargetProperty="{x:Static Entry.FontSizeProperty}" To="16"/>
<mauianimation:AnimateColor TargetProperty="{x:Static Entry.TextColorProperty}" To="Black"/>
<mauianimation:AnimateColor TargetProperty="{x:Static VisualElement.BackgroundColorProperty}" To="LightGray"/>
<mauianimation:AnimateDouble TargetProperty="{x:Static VisualElement.RotationProperty}" To="0"/>
</Trigger.ExitActions>
</Trigger>
</Entry.Triggers>
</Entry>
</StackLayout>
</ContentPage>
</ShellContent>
</Tab>
<!-- PROGRESS ANIMATIONS -->
<Tab
Title="Progress">
<ShellContent>
<ContentPage
Title="Progress Animations">
<ScrollView>
<VisualElement.Behaviors>
<mauianimation:ScrollViewScrollBehavior x:Name="ScrollBehavior" />
</VisualElement.Behaviors>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- HEADER IMAGE -->
<Image
x:Name="HeaderImage"
Source="maui.png"
Aspect="AspectFill"
HorizontalOptions="FillAndExpand">
<VisualElement.Behaviors>
<mauianimation:AnimateProgressDouble
TargetProperty="VisualElement.TranslationY"
Progress="{Binding ScrollY, Source={x:Reference ScrollBehavior}}"
Minimum="0"
Maximum="200"
From="0"
To="100"/>
</VisualElement.Behaviors>
</Image>
<Grid
Grid.Row="1"
BackgroundColor="Black"
HeightRequest="1000"
Padding="12">
<VisualElement.Behaviors>
<mauianimation:AnimateProgressColor
TargetProperty="VisualElement.BackgroundColor"
Progress="{Binding ScrollY, Source={x:Reference ScrollBehavior}}"
Minimum="0"
Maximum="200"
From="Black"
To="Red"/>
</VisualElement.Behaviors>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Column="0"
Grid.Row="0"
Text="ScrollY:"
TextColor="White"
VerticalOptions="Center"/>
<Label
Grid.Column="1"
Grid.Row="0"
Text="{Binding Source={x:Reference ScrollBehavior}, Path=ScrollY}"
TextColor="White"
VerticalOptions="Center">
<VisualElement.Behaviors>
<mauianimation:AnimateProgressDouble
TargetProperty="Label.FontSize"
Progress="{Binding ScrollY, Source={x:Reference ScrollBehavior}}"
Minimum="0"
Maximum="200"
From="12"
To="24"/>
</VisualElement.Behaviors>
</Label>
<Label
Grid.Column="0"
Grid.Row="1"
Text="Header TranslationY:"
TextColor="White"
VerticalOptions="Center"/>
<Label
Grid.Column="1"
Grid.Row="1"
Text="{Binding Source={x:Reference HeaderImage}, Path=TranslationY, StringFormat='{0:N}'}"
TextColor="White"
VerticalOptions="Center">
<VisualElement.Behaviors>
<mauianimation:AnimateProgressDouble
TargetProperty="Label.FontSize"
Progress="{Binding ScrollY, Source={x:Reference ScrollBehavior}}"
Minimum="0"
Maximum="200"
From="12"
To="24"/>
</VisualElement.Behaviors>
</Label>
</Grid>
</Grid>
</ScrollView>
</ContentPage>
</ShellContent>
</Tab>
<!-- TRANSITIONS -->
<Tab
Title="Transitions">
<ShellContent>
<ContentPage
Title="Entrance Transitions">
<Grid
x:Name="EntranceGrid">
<FlexLayout
Wrap="Wrap"
Direction="Row"
JustifyContent="Start"
AlignItems="Start"
AlignContent="Start"
Padding="6">
<FlexLayout.Resources>
<Style TargetType="BoxView">
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="HeightRequest" Value="100" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="Margin" Value="0, 6, 6, 0" />
</Style>
</FlexLayout.Resources>
<FlexLayout.Behaviors>
<mauianimation:EntranceTransition
Duration="1000"/>
</FlexLayout.Behaviors>
<BoxView
Color="Red" />
<BoxView
Color="Blue" />
<BoxView
Color="Green" />
<BoxView
Color="Yellow" />
<BoxView
Color="Pink" />
<BoxView
Color="Purple" />
<BoxView
Color="Black" />
<BoxView
Color="Orange" />
<BoxView
Color="LightBlue" />
</FlexLayout>
</Grid>
</ContentPage>
</ShellContent>
</Tab>
</TabBar>
</Shell>

Просмотреть файл

@ -0,0 +1,10 @@
namespace MauiAnimation.Sample
{
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<RootNamespace>MauiAnimation.Sample</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Display name -->
<ApplicationTitle>MauiAnimation.Sample</ApplicationTitle>
<!-- App Identifier -->
<ApplicationId>com.companyname.mauianimation.sample</ApplicationId>
<ApplicationIdGuid>91E0A936-DD95-425A-BC0E-A01B0633D406</ApplicationIdGuid>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#512BD4" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" BaseSize="128,128" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<None Remove="Resources\Images\heart.png" />
<None Remove="Resources\Images\maui.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MauiAnimation\MauiAnimation.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,19 @@
namespace MauiAnimation.Sample
{
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
return builder.Build();
}
}
}

Просмотреть файл

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

Просмотреть файл

@ -0,0 +1,11 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
namespace MauiAnimation.Sample
{
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
}
}

Просмотреть файл

@ -0,0 +1,16 @@
using Android.App;
using Android.Runtime;
namespace MauiAnimation.Sample
{
[Application]
public class MainApplication : MauiApplication
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership)
{
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#512BD4</color>
<color name="colorPrimaryDark">#2B0B98</color>
<color name="colorAccent">#2B0B98</color>
</resources>

Просмотреть файл

@ -0,0 +1,10 @@
using Foundation;
namespace MauiAnimation.Sample
{
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}

Просмотреть файл

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,16 @@
using ObjCRuntime;
using UIKit;
namespace MauiAnimation.Sample
{
public class Program
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using Microsoft.Maui;
using Microsoft.Maui.Hosting;
using System;
namespace MauiAnimation.Sample
{
internal class Program : MauiApplication
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
static void Main(string[] args)
{
var app = new Program();
app.Run(args);
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.companyname.MauiAnimation.Sample" version="1.0.0" api-version="7" xmlns="http://tizen.org/ns/packages">
<profile name="common" />
<ui-application appid="com.companyname.MauiAnimation.Sample" exec="MauiAnimation.Sample.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
<label>MauiAnimation.Sample</label>
<icon>appicon.xhigh.png</icon>
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
</ui-application>
<shortcut-list />
<privileges>
<privilege>http://tizen.org/privilege/internet</privilege>
</privileges>
<dependencies />
<provides-appdefined-privileges />
</manifest>

Просмотреть файл

@ -0,0 +1,8 @@
<maui:MauiWinUIApplication
x:Class="MauiAnimation.Sample.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maui="using:Microsoft.Maui"
xmlns:local="using:MauiAnimation.Sample.WinUI">
</maui:MauiWinUIApplication>

Просмотреть файл

@ -0,0 +1,24 @@
using Microsoft.UI.Xaml;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace MauiAnimation.Sample.WinUI
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : MauiWinUIApplication
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}

Просмотреть файл

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity Publisher="CN=User Name" />
<Properties>
<PublisherDisplayName>User Name</PublisherDisplayName>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.24217.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" MinVersion="14.0.24217.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements />
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

Просмотреть файл

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MauiAnimation.Sample.WinUI.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- The combination of below two tags have the following effect:
1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update
-->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>

Просмотреть файл

@ -0,0 +1,10 @@
using Foundation;
namespace MauiAnimation.Sample
{
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}

Просмотреть файл

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,16 @@
using ObjCRuntime;
using UIKit;
namespace MauiAnimation.Sample
{
public class Program
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"profiles": {
"Windows Machine": {
"commandName": "MsixPackage",
"nativeDebugging": false
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Color x:Key="Primary">#512BD4</Color>
<Color x:Key="Light">#DFD8F7</Color>
<Color x:Key="Dark">#2B0B98</Color>
<Color x:Key="White">White</Color>
<Color x:Key="Black">Black</Color>
<Color x:Key="LightGray">#E5E5E1</Color>
<Color x:Key="MidGray">#969696</Color>
<Color x:Key="DarkGray">#505050</Color>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
<SolidColorBrush x:Key="LightBrush" Color="{StaticResource Light}"/>
<SolidColorBrush x:Key="DarkBrush" Color="{StaticResource Dark}"/>
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
<SolidColorBrush x:Key="LightGrayBrush" Color="{StaticResource LightGray}"/>
<SolidColorBrush x:Key="MidGrayBrush" Color="{StaticResource MidGray}"/>
<SolidColorBrush x:Key="DarkGrayBrush" Color="{StaticResource DarkGray}"/>
<Color x:Key="Yellow100Accent">#F7B548</Color>
<Color x:Key="Yellow200Accent">#FFD590</Color>
<Color x:Key="Yellow300Accent">#FFE5B9</Color>
<Color x:Key="Cyan100Accent">#28C2D1</Color>
<Color x:Key="Cyan200Accent">#7BDDEF</Color>
<Color x:Key="Cyan300Accent">#C3F2F4</Color>
<Color x:Key="Blue100Accent">#3E8EED</Color>
<Color x:Key="Blue200Accent">#72ACF1</Color>
<Color x:Key="Blue300Accent">#A7CBF6</Color>
</ResourceDictionary>

Двоичные данные
src/MauiAnimation.Sample/Resources/Fonts/OpenSans-Regular.ttf Normal file

Двоичный файл не отображается.

Двоичные данные
src/MauiAnimation.Sample/Resources/Fonts/OpenSans-Semibold.ttf Normal file

Двоичный файл не отображается.

Двоичные данные
src/MauiAnimation.Sample/Resources/Images/heart.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичные данные
src/MauiAnimation.Sample/Resources/Images/maui.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.0 MiB

Просмотреть файл

@ -0,0 +1,14 @@
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories) and given a Build Action of "MauiAsset":
<MauiAsset Include="AboutAssets.txt" />
These files will be deployed with you package and will be accessible using Essentials:
async Task LoadMauiAsset()
{
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
}

Просмотреть файл

@ -0,0 +1,367 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Style TargetType="ActivityIndicator">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="IndicatorView">
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}"/>
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}"/>
</Style>
<Style TargetType="Border">
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="StrokeShape" Value="Rectangle"/>
<Setter Property="StrokeThickness" Value="1"/>
</Style>
<Style TargetType="BoxView">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}" />
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="14,10"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="DatePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Editor">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Frame">
<Setter Property="HasShadow" Value="False" />
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="CornerRadius" Value="8" />
</Style>
<Style TargetType="ImageButton">
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderColor" Value="Transparent"/>
<Setter Property="BorderWidth" Value="0"/>
<Setter Property="CornerRadius" Value="0"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Opacity" Value="0.5" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
</Style>
<Style TargetType="ListView">
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}" />
</Style>
<Style TargetType="Picker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ProgressBar">
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RefreshView">
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}" />
</Style>
<Style TargetType="SearchBar">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource MidGray}" />
<Setter Property="CancelButtonColor" Value="{StaticResource MidGray}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SearchHandler">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource MidGray}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Shadow">
<Setter Property="Radius" Value="15" />
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Offset" Value="10,10" />
</Style>
<Style TargetType="Slider">
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}"/>
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}"/>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SwipeItem">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style TargetType="Switch">
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="ThumbColor" Value="{StaticResource White}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Light}, Dark={StaticResource LightGray}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Off">
<VisualState.Setters>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="TimePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Page" ApplyToDerivedTypes="True">
<Setter Property="Padding" Value="0"/>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style x:Key="BaseStyle" TargetType="Element">
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Black}}" />
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource White}}" />
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="Shell.NavBarHasShadow" Value="False" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
</Style>
<Style BasedOn="{StaticResource BaseStyle}" TargetType="ShellItem" ApplyToDerivedTypes="True" />
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Black}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource White}}" />
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="TabbedPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource LightGray}, Dark={StaticResource DarkGray}}" />
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource DarkGray}, Dark={StaticResource LightGray}}" />
</Style>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 228 B

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

33
src/MauiAnimation.sln Normal file
Просмотреть файл

@ -0,0 +1,33 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32422.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiAnimation", "MauiAnimation\MauiAnimation.csproj", "{D4DA03B0-7212-4478-AB58-F9772FC5F518}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiAnimation.Sample", "MauiAnimation.Sample\MauiAnimation.Sample.csproj", "{BAC85A14-6536-45EC-8CFB-02690EF502AA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4DA03B0-7212-4478-AB58-F9772FC5F518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4DA03B0-7212-4478-AB58-F9772FC5F518}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4DA03B0-7212-4478-AB58-F9772FC5F518}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4DA03B0-7212-4478-AB58-F9772FC5F518}.Release|Any CPU.Build.0 = Release|Any CPU
{BAC85A14-6536-45EC-8CFB-02690EF502AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAC85A14-6536-45EC-8CFB-02690EF502AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAC85A14-6536-45EC-8CFB-02690EF502AA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{BAC85A14-6536-45EC-8CFB-02690EF502AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAC85A14-6536-45EC-8CFB-02690EF502AA}.Release|Any CPU.Build.0 = Release|Any CPU
{BAC85A14-6536-45EC-8CFB-02690EF502AA}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F5943221-9C71-4691-A477-3B9EF93C1783}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,104 @@
namespace MauiAnimation
{
using System.Threading;
using System.Threading.Tasks;
public abstract class AnimationBase : BindableObject
{
private CancellationTokenSource _animateTimerCancellationTokenSource;
public static readonly BindableProperty TargetProperty =
BindableProperty.Create(nameof(Target), typeof(VisualElement), typeof(AnimationBase), null,
BindingMode.TwoWay, null);
public VisualElement Target
{
get { return (VisualElement)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
public static readonly BindableProperty DurationProperty =
BindableProperty.Create(nameof(Duration), typeof(string), typeof(AnimationBase), "1000",
BindingMode.TwoWay, null);
public string Duration
{
get { return (string)GetValue(DurationProperty); }
set { SetValue(DurationProperty, value); }
}
public static readonly BindableProperty EasingProperty =
BindableProperty.Create(nameof(Easing), typeof(EasingType), typeof(AnimationBase), EasingType.Linear,
BindingMode.TwoWay, null);
public EasingType Easing
{
get { return (EasingType)GetValue(EasingProperty); }
set { SetValue(EasingProperty, value); }
}
public static readonly BindableProperty DelayProperty =
BindableProperty.Create("Delay", typeof(int), typeof(AnimationBase), 0, propertyChanged: (bindable, oldValue, newValue) =>
((AnimationBase)bindable).Delay = (int)newValue);
public int Delay
{
get { return (int)GetValue(DelayProperty); }
set { SetValue(DelayProperty, value); }
}
public static readonly BindableProperty RepeatForeverProperty =
BindableProperty.Create("RepeatForever", typeof(bool), typeof(AnimationBase), false, propertyChanged: (bindable, oldValue, newValue) =>
((AnimationBase)bindable).RepeatForever = (bool)newValue);
public bool RepeatForever
{
get { return (bool)GetValue(RepeatForeverProperty); }
set { SetValue(RepeatForeverProperty, value); }
}
protected abstract Task BeginAnimation();
public async Task Begin()
{
if (Delay > 0)
{
await Task.Delay(Delay);
}
if (!RepeatForever)
{
await BeginAnimation();
}
else
{
RepeatAnimation(new CancellationTokenSource());
}
}
public void End()
{
Microsoft.Maui.Controls.ViewExtensions.CancelAnimations(Target);
if (_animateTimerCancellationTokenSource != null)
{
_animateTimerCancellationTokenSource.Cancel();
}
}
internal void RepeatAnimation(CancellationTokenSource tokenSource)
{
_animateTimerCancellationTokenSource = tokenSource;
Device.BeginInvokeOnMainThread(async () =>
{
if (!_animateTimerCancellationTokenSource.IsCancellationRequested)
{
await BeginAnimation();
RepeatAnimation(_animateTimerCancellationTokenSource);
}
});
}
}
}

Просмотреть файл

@ -0,0 +1,82 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class BounceInAnimation : AnimationBase
{
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("BounceIn", BounceIn(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation BounceIn()
{
var animation = new Animation();
animation.WithConcurrent(
f => Target.Scale = f,
0.5, 1,
Microsoft.Maui.Easing.Linear, 0, 1);
animation.WithConcurrent(
(f) => Target.Opacity = f,
0, 1,
null,
0, 0.25);
return animation;
}
}
public class BounceOutAnimation : AnimationBase
{
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("BounceOut", BounceOut(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation BounceOut()
{
var animation = new Animation();
Target.Opacity = 1;
animation.WithConcurrent(
(f) => Target.Opacity = f,
1, 0,
null,
0.5, 1);
animation.WithConcurrent(
(f) => Target.Scale = f,
1, 0.3,
Microsoft.Maui.Easing.Linear, 0, 1);
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class ColorAnimation : AnimationBase
{
public static readonly BindableProperty ToColorProperty =
BindableProperty.Create(nameof(ToColor), typeof(Color), typeof(ColorAnimation), Colors.Transparent,
BindingMode.TwoWay, null);
public Color ToColor
{
get { return (Color)GetValue(ToColorProperty); }
set { SetValue(ToColorProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
var fromColor = Target.BackgroundColor;
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(async () =>
{
await Target.ColorTo(fromColor, ToColor, c => Target.BackgroundColor = c, Convert.ToUInt32(Duration));
});
});
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
namespace MauiAnimation
{
public enum EasingType
{
BounceIn,
BounceOut,
CubicIn,
CubicInOut,
CubicOut,
Linear,
SinIn,
SinInOut,
SinOut,
SpringIn,
SpringOut
}
}

Просмотреть файл

@ -0,0 +1,128 @@
namespace MauiAnimation
{
using Helpers;
using System;
using System.Threading.Tasks;
public class FadeToAnimation : AnimationBase
{
public static readonly BindableProperty OpacityProperty =
BindableProperty.Create(nameof(Opacity), typeof(double), typeof(FadeToAnimation), default(double),
BindingMode.TwoWay, null);
public double Opacity
{
get { return (double)GetValue(OpacityProperty); }
set { SetValue(OpacityProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.FadeTo(Opacity, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
public class FadeInAnimation : AnimationBase
{
public enum FadeDirection
{
Up,
Down
}
public static readonly BindableProperty DirectionProperty =
BindableProperty.Create(nameof(Direction), typeof(FadeDirection), typeof(FadeInAnimation), FadeDirection.Up,
BindingMode.TwoWay, null);
public FadeDirection Direction
{
get { return (FadeDirection)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("FadeIn", FadeIn(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation FadeIn()
{
var animation = new Animation();
animation.WithConcurrent((f) => Target.Opacity = f, 0, 1, Microsoft.Maui.Easing.CubicOut);
animation.WithConcurrent(
(f) => Target.TranslationY = f,
Target.TranslationY + ((Direction == FadeDirection.Up) ? 50 : -50), Target.TranslationY,
Microsoft.Maui.Easing.CubicOut, 0, 1);
return animation;
}
}
public class FadeOutAnimation : AnimationBase
{
public enum FadeDirection
{
Up,
Down
}
public static readonly BindableProperty DirectionProperty =
BindableProperty.Create(nameof(Direction), typeof(FadeDirection), typeof(FadeOutAnimation), FadeDirection.Up,
BindingMode.TwoWay, null);
public FadeDirection Direction
{
get { return (FadeDirection)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("FadeOut", FadeOut(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation FadeOut()
{
var animation = new Animation();
animation.WithConcurrent(
(f) => Target.Opacity = f,
1, 0);
animation.WithConcurrent(
(f) => Target.TranslationY = f,
Target.TranslationY, Target.TranslationY + ((Direction == FadeDirection.Up) ? 50 : -50));
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class FlipAnimation : AnimationBase
{
public enum FlipDirection
{
Left,
Right
}
public static readonly BindableProperty DirectionProperty =
BindableProperty.Create(nameof(Direction), typeof(FlipDirection), typeof(FlipAnimation), FlipDirection.Right,
BindingMode.TwoWay, null);
public FlipDirection Direction
{
get { return (FlipDirection)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("Flip", Flip(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation Flip()
{
var animation = new Animation();
animation.WithConcurrent((f) => Target.Opacity = f, 0.5, 1);
animation.WithConcurrent((f) => Target.RotationY = f, (Direction == FlipDirection.Left) ? 90 : -90, 0, Microsoft.Maui.Easing.Linear);
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,56 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class HeartAnimation : AnimationBase
{
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("Hearth", Hearth(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation Hearth()
{
var animation = new Animation();
animation.WithConcurrent(
(f) => Target.Scale = f,
Target.Scale, Target.Scale,
Microsoft.Maui.Easing.Linear, 0, 0.1);
animation.WithConcurrent(
(f) => Target.Scale = f,
Target.Scale, Target.Scale * 1.1,
Microsoft.Maui.Easing.Linear, 0.1, 0.4);
animation.WithConcurrent(
(f) => Target.Scale = f,
Target.Scale * 1.1, Target.Scale,
Microsoft.Maui.Easing.Linear, 0.4, 0.5);
animation.WithConcurrent(
(f) => Target.Scale = f,
Target.Scale, Target.Scale * 1.1,
Microsoft.Maui.Easing.Linear, 0.5, 0.8);
animation.WithConcurrent(
(f) => Target.Scale = f,
Target.Scale * 1.1, Target.Scale,
Microsoft.Maui.Easing.Linear, 0.8, 1);
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,48 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class JumpAnimation : AnimationBase
{
private const int Movement = -25;
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("Jump", Jump(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation Jump()
{
var animation = new Animation();
animation.WithConcurrent(
(f) => Target.TranslationY = f,
Target.TranslationY, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0, 0.2);
animation.WithConcurrent(
(f) => Target.TranslationY = f,
Target.TranslationY + Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.2, 0.4);
animation.WithConcurrent(
(f) => Target.TranslationY = f,
Target.TranslationY, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.5, 1.0);
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,98 @@
namespace MauiAnimation
{
using Helpers;
using System;
using System.Threading.Tasks;
public class RotateToAnimation : AnimationBase
{
public static readonly BindableProperty RotationProperty =
BindableProperty.Create(nameof(Rotation), typeof(double), typeof(RotateToAnimation), default(double),
BindingMode.TwoWay, null);
public double Rotation
{
get { return (double)GetValue(RotationProperty); }
set { SetValue(RotationProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.RotateTo(Rotation, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
public class RelRotateToAnimation : AnimationBase
{
public static readonly BindableProperty RotationProperty =
BindableProperty.Create(nameof(Rotation), typeof(double), typeof(RelRotateToAnimation), default(double),
BindingMode.TwoWay, null);
public double Rotation
{
get { return (double)GetValue(RotationProperty); }
set { SetValue(RotationProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.RelRotateTo(Rotation, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
public class RotateXToAnimation : AnimationBase
{
public static readonly BindableProperty RotationProperty =
BindableProperty.Create(nameof(Rotation), typeof(double), typeof(RotateXToAnimation), default(double),
BindingMode.TwoWay, null);
public double Rotation
{
get { return (double)GetValue(RotationProperty); }
set { SetValue(RotationProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.RotateXTo(Rotation, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
public class RotateYToAnimation : AnimationBase
{
public static readonly BindableProperty RotationProperty =
BindableProperty.Create(nameof(Rotation), typeof(double), typeof(RotateYToAnimation), default(double),
BindingMode.TwoWay, null);
public double Rotation
{
get { return (double)GetValue(RotationProperty); }
set { SetValue(RotationProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.RotateYTo(Rotation, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,52 @@
namespace MauiAnimation
{
using Helpers;
using System;
using System.Threading.Tasks;
public class ScaleToAnimation : AnimationBase
{
public static readonly BindableProperty ScaleProperty =
BindableProperty.Create(nameof(Scale), typeof(double), typeof(ScaleToAnimation), default(double),
BindingMode.TwoWay, null);
public double Scale
{
get { return (double)GetValue(ScaleProperty); }
set { SetValue(ScaleProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.ScaleTo(Scale, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
public class RelScaleToAnimation : AnimationBase
{
public static readonly BindableProperty ScaleProperty =
BindableProperty.Create(nameof(Scale), typeof(double), typeof(RelScaleToAnimation), default(double),
BindingMode.TwoWay, null);
public double Scale
{
get { return (double)GetValue(ScaleProperty); }
set { SetValue(ScaleProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.RelScaleTo(Scale, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,73 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class ShakeAnimation : AnimationBase
{
private const int Movement = 5;
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("Shake", Shake(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation Shake()
{
var animation = new Animation();
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX + Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0, 0.1);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX - Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.1, 0.2);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX + Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.2, 0.3);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX - Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.3, 0.4);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX + Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.4, 0.5);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX - Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.5, 0.6);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX + Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.6, 0.7);
animation.WithConcurrent(
(f) => Target.TranslationX = f,
Target.TranslationX - Movement, Target.TranslationX,
Microsoft.Maui.Easing.Linear, 0.7, 0.8);
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
namespace MauiAnimation
{
using System.Collections.Generic;
using System.Threading.Tasks;
[ContentProperty("Animations")]
public class StoryBoard : AnimationBase
{
public StoryBoard()
{
Animations = new List<AnimationBase>();
}
public StoryBoard(List<AnimationBase> animations)
{
Animations = animations;
}
public List<AnimationBase> Animations
{
get;
}
protected override async Task BeginAnimation()
{
foreach (var animation in Animations)
{
if (animation.Target == null)
animation.Target = Target;
await animation.Begin();
}
}
}
}

Просмотреть файл

@ -0,0 +1,39 @@
namespace MauiAnimation
{
using Helpers;
using System;
using System.Threading.Tasks;
public class TranslateToAnimation : AnimationBase
{
public static readonly BindableProperty TranslateXProperty =
BindableProperty.Create(nameof(TranslateX), typeof(double), typeof(TranslateToAnimation), default(double),
BindingMode.TwoWay, null);
public double TranslateX
{
get { return (double)GetValue(TranslateXProperty); }
set { SetValue(TranslateXProperty, value); }
}
public static readonly BindableProperty TranslateYProperty =
BindableProperty.Create(nameof(TranslateY), typeof(double), typeof(TranslateToAnimation), default(double),
BindingMode.TwoWay, null);
public double TranslateY
{
get { return (double)GetValue(TranslateYProperty); }
set { SetValue(TranslateYProperty, value); }
}
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Target.TranslateTo(TranslateX, TranslateY, Convert.ToUInt32(Duration), EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public class TurnstileInAnimation : AnimationBase
{
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("TurnstileIn", TurnstileIn(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation TurnstileIn()
{
var animation = new Animation();
animation.WithConcurrent((f) => Target.RotationY = f, 75, 0, Microsoft.Maui.Easing.CubicOut);
animation.WithConcurrent((f) => Target.Opacity = f, 0, 1, null, 0, 0.01);
return animation;
}
}
public class TurnstileOutAnimation : AnimationBase
{
protected override Task BeginAnimation()
{
if (Target == null)
{
throw new NullReferenceException("Null Target property.");
}
return Task.Run(() =>
{
Device.BeginInvokeOnMainThread(() =>
{
Target.Animate("TurnstileOut", TurnstileOut(), 16, Convert.ToUInt32(Duration));
});
});
}
internal Animation TurnstileOut()
{
var animation = new Animation();
animation.WithConcurrent((f) => Target.RotationY = f, 0, -75, Microsoft.Maui.Easing.CubicOut);
animation.WithConcurrent((f) => Target.Opacity = f, 1, 0, null, 0.9, 1);
return animation;
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
namespace MauiAnimation
{
public class AnimateProgressColor : AnimationProgressBaseBehavior
{
public static readonly BindableProperty FromProperty =
BindableProperty.Create(nameof(From), typeof(Color), typeof(AnimationProgressBaseBehavior), default(Color),
BindingMode.TwoWay, null);
public Color From
{
get { return (Color)GetValue(FromProperty); }
set { SetValue(FromProperty, value); }
}
public static readonly BindableProperty ToProperty =
BindableProperty.Create(nameof(To), typeof(Color), typeof(AnimationProgressBaseBehavior), default(Color),
BindingMode.TwoWay, null);
public Color To
{
get { return (Color)GetValue(ToProperty); }
set { SetValue(ToProperty, value); }
}
protected override void OnUpdate()
{
if (From == null && To == null)
return;
if (From == null)
{
Target.SetValue(TargetProperty, To);
return;
}
if (To == null)
{
Target.SetValue(TargetProperty, From);
return;
}
var newR = (To.Red - From.Red) * Progress;
var newG = (To.Green - From.Green) * Progress;
var newB = (To.Blue - From.Blue) * Progress;
Color value = Color.FromRgb((int)(From.Red + newR), (int)(From.Green + newG), (int)(From.Blue + newB));
Target.SetValue(TargetProperty, value);
}
}
}

Просмотреть файл

@ -0,0 +1,43 @@
namespace MauiAnimation
{
public class AnimateProgressCornerRadius : AnimationProgressBaseBehavior
{
public static readonly BindableProperty FromProperty =
BindableProperty.Create(nameof(From), typeof(CornerRadius), typeof(AnimationProgressBaseBehavior), default(CornerRadius),
BindingMode.TwoWay, null);
public CornerRadius From
{
get { return (CornerRadius)GetValue(FromProperty); }
set { SetValue(FromProperty, value); }
}
public static readonly BindableProperty ToProperty =
BindableProperty.Create(nameof(To), typeof(CornerRadius), typeof(AnimationProgressBaseBehavior), default(CornerRadius),
BindingMode.TwoWay, null);
public CornerRadius To
{
get { return (CornerRadius)GetValue(ToProperty); }
set { SetValue(ToProperty, value); }
}
protected override void OnUpdate()
{
if (Progress < Minimum)
return;
if (Progress >= Maximum)
return;
double? topLeft = ((Progress - Minimum) * (To.TopLeft - From.TopLeft) / (Maximum - Minimum)) + From.TopLeft;
double? topRight = ((Progress - Minimum) * (To.TopRight - From.TopRight) / (Maximum - Minimum)) + From.TopRight;
double? bottomLeft = ((Progress - Minimum) * (To.BottomLeft - From.BottomLeft) / (Maximum - Minimum)) + From.BottomLeft;
double? bottomRight = ((Progress - Minimum) * (To.BottomRight - From.BottomRight) / (Maximum - Minimum)) + From.BottomRight;
CornerRadius value = new CornerRadius(topLeft.Value, topRight.Value, bottomLeft.Value, bottomRight.Value);
Target.SetValue(TargetProperty, value);
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
namespace MauiAnimation
{
public class AnimateProgressDouble : AnimationProgressBaseBehavior
{
public static readonly BindableProperty FromProperty =
BindableProperty.Create(nameof(From), typeof(double), typeof(AnimationProgressBaseBehavior), default(double),
BindingMode.TwoWay, null);
public double From
{
get { return (double)GetValue(FromProperty); }
set { SetValue(FromProperty, value); }
}
public static readonly BindableProperty ToProperty =
BindableProperty.Create(nameof(To), typeof(double), typeof(AnimationProgressBaseBehavior), default(double),
BindingMode.TwoWay, null);
public double To
{
get { return (double)GetValue(ToProperty); }
set { SetValue(ToProperty, value); }
}
public static readonly BindableProperty MultiplyValueProperty =
BindableProperty.Create(nameof(MultiplyValue), typeof(double), typeof(AnimateProgressDouble), 1.0d,
BindingMode.TwoWay, null);
public double MultiplyValue
{
get { return (double)GetValue(MultiplyValueProperty); }
set { SetValue(MultiplyValueProperty, value); }
}
protected override void OnUpdate()
{
if (Progress < Minimum) {
Target.SetValue(TargetProperty, From * MultiplyValue);
return;
}
if (Progress >= Maximum) {
Target.SetValue(TargetProperty, To * MultiplyValue);
return;
}
//Formula Used
//Y = ((X - X1)*(Y2 - Y1) / (X2 - X1)) + Y1
double? value = ((Progress - Minimum) * (To - From) / (Maximum - Minimum)) + From;
Target.SetValue(TargetProperty, value.GetValueOrDefault() * MultiplyValue);
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
namespace MauiAnimation.Behaviors
{
public class AnimateProgressInt : AnimationProgressBaseBehavior
{
public static readonly BindableProperty FromProperty =
BindableProperty.Create(nameof(From), typeof(int), typeof(AnimationProgressBaseBehavior), default(int),
BindingMode.TwoWay, null);
public int From
{
get { return (int)GetValue(FromProperty); }
set { SetValue(FromProperty, value); }
}
public static readonly BindableProperty ToProperty =
BindableProperty.Create(nameof(To), typeof(int), typeof(AnimationProgressBaseBehavior), default(int),
BindingMode.TwoWay, null);
public int To
{
get { return (int)GetValue(ToProperty); }
set { SetValue(ToProperty, value); }
}
protected override void OnUpdate()
{
if (Progress < Minimum) {
Target.SetValue(TargetProperty, From);
return;
}
if (Progress >= Maximum) {
Target.SetValue(TargetProperty, To);
return;
}
int? value = (int)(((Progress - Minimum) * (To - From) / (Maximum - Minimum)) + From);
Target.SetValue(TargetProperty, value.GetValueOrDefault());
}
}
}

Просмотреть файл

@ -0,0 +1,43 @@
namespace MauiAnimation
{
public class AnimateProgressThickness : AnimationProgressBaseBehavior
{
public static readonly BindableProperty FromProperty =
BindableProperty.Create(nameof(From), typeof(Thickness), typeof(AnimationProgressBaseBehavior), default(Thickness),
BindingMode.TwoWay, null);
public Thickness From
{
get { return (Thickness)GetValue(FromProperty); }
set { SetValue(FromProperty, value); }
}
public static readonly BindableProperty ToProperty =
BindableProperty.Create(nameof(To), typeof(Thickness), typeof(AnimationProgressBaseBehavior), default(Thickness),
BindingMode.TwoWay, null);
public Thickness To
{
get { return (Thickness)GetValue(ToProperty); }
set { SetValue(ToProperty, value); }
}
protected override void OnUpdate()
{
if (Progress < Minimum)
return;
if (Progress >= Maximum)
return;
double? left = ((Progress - Minimum) * (To.Left - From.Left) / (Maximum - Minimum)) + From.Left;
double? top = ((Progress - Minimum) * (To.Top - From.Top) / (Maximum - Minimum)) + From.Top;
double? right = ((Progress - Minimum) * (To.Right - From.Right) / (Maximum - Minimum)) + From.Right;
double? bottom = ((Progress - Minimum) * (To.Bottom - From.Bottom) / (Maximum - Minimum)) + From.Bottom;
Thickness value = new Thickness(left.Value, top.Value, right.Value, bottom.Value);
Target.SetValue(TargetProperty, value);
}
}
}

Просмотреть файл

@ -0,0 +1,89 @@
namespace MauiAnimation
{
public abstract class AnimationProgressBaseBehavior : Behavior<VisualElement>
{
public static readonly BindableProperty ProgressProperty =
BindableProperty.Create(nameof(Progress), typeof(double?), typeof(AnimationProgressBaseBehavior), default(double),
BindingMode.TwoWay, null, OnChanged);
public double? Progress
{
get { return (double?)GetValue(ProgressProperty); }
set { SetValue(ProgressProperty, value); }
}
public static readonly BindableProperty MinimumProperty =
BindableProperty.Create(nameof(Minimum), typeof(double), typeof(AnimationProgressBaseBehavior), 0.0d,
BindingMode.TwoWay, null);
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly BindableProperty MaximumProperty =
BindableProperty.Create(nameof(Maximum), typeof(double), typeof(AnimationProgressBaseBehavior), 100.0d,
BindingMode.TwoWay, null);
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly BindableProperty EasingProperty =
BindableProperty.Create(nameof(Easing), typeof(EasingType), typeof(AnimationProgressBaseBehavior), EasingType.Linear,
BindingMode.TwoWay, null);
public EasingType Easing
{
get { return (EasingType)GetValue(EasingProperty); }
set { SetValue(EasingProperty, value); }
}
public static readonly BindableProperty TargetPropertyProperty =
BindableProperty.Create(nameof(TargetProperty), typeof(BindableProperty), typeof(AnimationProgressBaseBehavior), null,
BindingMode.TwoWay, null);
public BindableProperty TargetProperty
{
get { return (BindableProperty)GetValue(TargetPropertyProperty); }
set { SetValue(TargetPropertyProperty, value); }
}
public VisualElement Target
{
get;
private set;
}
protected override void OnAttachedTo(VisualElement bindable)
{
Target = bindable;
Update();
base.OnAttachedTo(bindable);
}
protected static void OnChanged(BindableObject bindable, object oldValue, object newValue)
{
((AnimationProgressBaseBehavior)bindable).Update();
}
protected override void OnDetachingFrom(VisualElement bindable)
{
base.OnDetachingFrom(bindable);
Target = null;
}
protected abstract void OnUpdate();
protected void Update()
{
if (Target != null && Progress.HasValue)
{
OnUpdate();
}
}
}
}

Просмотреть файл

@ -0,0 +1,43 @@
namespace MauiAnimation
{
using System.Threading.Tasks;
public class BeginAnimationBehavior : Behavior<VisualElement>
{
private static VisualElement associatedObject;
protected override async void OnAttachedTo(VisualElement bindable)
{
base.OnAttachedTo(bindable);
associatedObject = bindable;
if (Animation != null)
{
if (Animation.Target == null)
{
Animation.Target = associatedObject;
}
var delay = Task.Delay(250);
await Task.WhenAll(delay);
await Animation.Begin();
}
}
protected override void OnDetachingFrom(VisualElement bindable)
{
associatedObject = null;
base.OnDetachingFrom(bindable);
}
public static readonly BindableProperty AnimationProperty =
BindableProperty.Create(nameof(Animation), typeof(AnimationBase), typeof(BeginAnimationBehavior), null,
BindingMode.TwoWay, null);
public AnimationBase Animation
{
get { return (AnimationBase)GetValue(AnimationProperty); }
set { SetValue(AnimationProperty, value); }
}
}
}

Просмотреть файл

@ -0,0 +1,39 @@
namespace MauiAnimation
{
public class EndAnimationBehavior : Behavior<VisualElement>
{
private static VisualElement associatedObject;
protected override void OnAttachedTo(VisualElement bindable)
{
base.OnAttachedTo(bindable);
associatedObject = bindable;
if (Animation != null)
{
if (Animation.Target == null)
{
Animation.Target = associatedObject;
}
Animation.End();
}
}
protected override void OnDetachingFrom(VisualElement bindable)
{
associatedObject = null;
base.OnDetachingFrom(bindable);
}
public static readonly BindableProperty AnimationProperty =
BindableProperty.Create(nameof(Animation), typeof(AnimationBase), typeof(BeginAnimationBehavior), null,
BindingMode.TwoWay, null);
public AnimationBase Animation
{
get { return (AnimationBase)GetValue(AnimationProperty); }
set { SetValue(AnimationProperty, value); }
}
}
}

Просмотреть файл

@ -0,0 +1,122 @@
namespace MauiAnimation
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MauiAnimation.Helpers;
public class EntranceTransition : Behavior<VisualElement>
{
const int Delay = 100;
const int TranslateFrom = 6;
private VisualElement _associatedObject;
private IEnumerable<VisualElement> _childrens;
public static readonly BindableProperty DurationProperty =
BindableProperty.Create(nameof(Duration), typeof(string), typeof(EntranceTransition), "500",
BindingMode.TwoWay, null);
public string Duration
{
get { return (string)GetValue(DurationProperty); }
set { SetValue(DurationProperty, value); }
}
protected override void OnAttachedTo(VisualElement bindable)
{
base.OnAttachedTo(bindable);
_associatedObject = bindable;
_childrens = VisualTreeHelper.GetChildren<VisualElement>(_associatedObject);
_associatedObject.PropertyChanged += OnPropertyChanged;
}
protected override void OnDetachingFrom(VisualElement bindable)
{
StopAnimation();
_associatedObject.PropertyChanged -= OnPropertyChanged;
_associatedObject = null;
_childrens = null;
base.OnDetachingFrom(bindable);
}
async void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Renderer")
{
await StartAnimationAsync();
}
}
void SetInitialTransitionState()
{
if (_childrens.Any())
{
foreach (var child in _childrens)
SetInitialTransitionState(child);
}
else
SetInitialTransitionState(_associatedObject);
}
void SetInitialTransitionState(VisualElement element)
{
element.Opacity = 0;
element.TranslationX = _associatedObject.TranslationX + TranslateFrom;
element.TranslationY = _associatedObject.TranslationY + TranslateFrom;
}
void StopAnimation()
{
if (_childrens.Any())
{
foreach (var child in _childrens)
Microsoft.Maui.Controls.ViewExtensions.CancelAnimations(child);
}
else
Microsoft.Maui.Controls.ViewExtensions.CancelAnimations(_associatedObject);
}
async Task StartAnimationAsync()
{
StopAnimation();
SetInitialTransitionState();
if (_childrens.Any())
{
foreach (var child in _childrens)
await AnimateItemAsync(child);
}
else
{
if(!HasParentEntranceTransition(_associatedObject))
await AnimateItemAsync(_associatedObject);
}
}
async Task AnimateItemAsync(VisualElement element)
{
await Task.Delay(Delay);
var parentAnimation = new Animation();
var translateXAnimation = new Animation(v => element.TranslationX = v, element.TranslationX, 0, Easing.SpringIn);
var translateYAnimation = new Animation(v => element.TranslationY = v, element.TranslationY, 0, Easing.SpringIn);
var opacityAnimation = new Animation(v => element.Opacity = v, 0, 1, Easing.CubicIn);
parentAnimation.Add(0, 0.75, translateXAnimation);
parentAnimation.Add(0, 0.75, translateYAnimation);
parentAnimation.Add(0, 1, opacityAnimation);
parentAnimation.Commit(_associatedObject, "EntranceTransition" + element.Id, 16, Convert.ToUInt32(Duration), null, (v, c) => StopAnimation());
}
bool HasParentEntranceTransition(VisualElement element)
{
VisualElement parent = VisualTreeHelper.GetParent<VisualElement>(element);
var behaviors = parent.Behaviors;
return behaviors.OfType<EntranceTransition>().FirstOrDefault() != null;
}
}
}

Просмотреть файл

@ -0,0 +1,113 @@
namespace MauiAnimation
{
public class ScrollViewScrollBehavior : Behavior<ScrollView>
{
public static readonly BindableProperty ScrollXProperty =
BindableProperty.Create(nameof(ScrollX), typeof(double), typeof(ScrollViewScrollBehavior), default(double),
BindingMode.TwoWay, null);
/// <summary>
/// The horizontal scroll value in pixels.
/// </summary>
public double ScrollX
{
get { return (double)GetValue(ScrollXProperty); }
set { SetValue(ScrollXProperty, value); }
}
public static readonly BindableProperty ScrollYProperty =
BindableProperty.Create(nameof(ScrollY), typeof(double), typeof(ScrollViewScrollBehavior), default(double),
BindingMode.TwoWay, null);
/// <summary>
/// The vertical scroll value in pixels.
/// </summary>
public double ScrollY
{
get { return (double)GetValue(ScrollYProperty); }
set { SetValue(ScrollYProperty, value); }
}
public static readonly BindableProperty RelativeScrollXProperty =
BindableProperty.Create(nameof(RelativeScrollX), typeof(double), typeof(ScrollViewScrollBehavior), default(double),
BindingMode.TwoWay, null);
/// <summary>
/// The horizontal scroll value between 0 and 1.
/// </summary>
public double RelativeScrollX
{
get { return (double)GetValue(RelativeScrollXProperty); }
set { SetValue(RelativeScrollXProperty, value); }
}
public static readonly BindableProperty RelativeScrollYProperty =
BindableProperty.Create(nameof(RelativeScrollY), typeof(double), typeof(ScrollViewScrollBehavior), default(double),
BindingMode.TwoWay, null);
/// <summary>
/// The vertical scroll value between 0 and 1.
/// </summary>
public double RelativeScrollY
{
get { return (double)GetValue(RelativeScrollYProperty); }
set { SetValue(RelativeScrollYProperty, value); }
}
public static readonly BindableProperty PercentageScrollXProperty =
BindableProperty.Create(nameof(PercentageScrollX), typeof(double), typeof(ScrollViewScrollBehavior), default(double),
BindingMode.TwoWay, null);
/// <summary>
/// The horizontal scroll value between 0% and 100%.
/// </summary>
public double PercentageScrollX
{
get { return (double)GetValue(PercentageScrollXProperty); }
set { SetValue(PercentageScrollXProperty, value); }
}
public static readonly BindableProperty PercentageScrollYProperty =
BindableProperty.Create(nameof(PercentageScrollY), typeof(double), typeof(ScrollViewScrollBehavior), default(double),
BindingMode.TwoWay, null);
/// <summary>
/// The vertical scroll value between 0% and 100%.
/// </summary>
public double PercentageScrollY
{
get { return (double)GetValue(PercentageScrollYProperty); }
set { SetValue(PercentageScrollYProperty, value); }
}
protected override void OnAttachedTo(ScrollView bindable)
{
base.OnAttachedTo(bindable);
bindable.Scrolled += new EventHandler<ScrolledEventArgs>(OnScrolled);
}
protected override void OnDetachingFrom(ScrollView bindable)
{
base.OnDetachingFrom(bindable);
bindable.Scrolled -= new EventHandler<ScrolledEventArgs>(OnScrolled);
}
private void OnScrolled(object sender, ScrolledEventArgs e)
{
ScrollY = e.ScrollY;
ScrollX = e.ScrollX;
ScrollView scrollView = (ScrollView)sender;
Size contentSize = scrollView.ContentSize;
var viewportHeight = contentSize.Height - scrollView.Height;
var viewportWidth = contentSize.Width - scrollView.Width;
RelativeScrollY = viewportHeight <= 0 ? 0 : e.ScrollY / viewportHeight;
RelativeScrollX = viewportWidth <= 0 ? 0 : e.ScrollX / viewportWidth;
PercentageScrollX = RelativeScrollX * 100;
PercentageScrollY = RelativeScrollY * 100;
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
namespace MauiAnimation
{
using System.Threading.Tasks;
public static class AnimationExtensions
{
public static async Task<bool> Animate(this VisualElement visualElement, AnimationBase animation)
{
try
{
animation.Target = visualElement;
await animation.Begin();
return true;
}
catch
{
return false;
}
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
// https://developer.xamarin.com/samples/xamarin-forms/userinterface/animation/custom/
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public static class ColorExtensions
{
public static Task<bool> ColorTo(this VisualElement self, Color fromColor, Color toColor, Action<Color> callback, uint length = 250, Easing easing = null)
{
Color transform(double t) =>
Color.FromRgba(fromColor.Red + t * (toColor.Red - fromColor.Red),
fromColor.Green + t * (toColor.Green - fromColor.Green),
fromColor.Blue + t * (toColor.Blue - fromColor.Blue),
fromColor.Alpha + t * (toColor.Alpha - fromColor.Alpha));
return ColorAnimation(self, "ColorTo", transform, callback, length, easing);
}
public static void CancelAnimation(this VisualElement self)
{
self.AbortAnimation("ColorTo");
}
static Task<bool> ColorAnimation(VisualElement element, string name, Func<double, Color> transform, Action<Color> callback, uint length, Easing easing)
{
easing = easing ?? Easing.Linear;
var taskCompletionSource = new TaskCompletionSource<bool>();
element.Animate<Color>(name, transform, callback, 16, length, easing, (v, c) => taskCompletionSource.SetResult(c));
return taskCompletionSource.Task;
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
public static class TaskExtensions
{
public static async void FireAndForget(this Task task, Action<Exception> onException = null)
{
try
{
await task;
}
catch (Exception ex)
{
onException?.Invoke(ex);
}
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
namespace MauiAnimation.Helpers
{
public static class AnimationHelper
{
public static int GetIntValue(int from, int to, double animationProgress)
{
return (int)(from + (to - from) * animationProgress);
}
public static double GetDoubleValue(double from, double to, double animationProgress)
{
return from + (to - from) * animationProgress;
}
// https://www.alanzucconi.com/2016/01/06/colour-interpolation/
public static Color GetColorValue(Color from, Color to, double animationProgress)
{
var newR = (to.Red - from.Red) * animationProgress;
var newG = (to.Green - from.Green) * animationProgress;
var newB = (to.Blue - from.Blue) * animationProgress;
return Color.FromRgb(from.Red + newR, from.Green + newG, from.Blue + newB);
}
public static CornerRadius GetCornerRadiusValue(CornerRadius from, CornerRadius to, double animationProgress)
{
return new CornerRadius(
from.TopLeft + (to.TopLeft - from.TopLeft) * animationProgress,
from.TopRight + (to.TopRight - from.TopRight) * animationProgress,
from.BottomLeft + (to.BottomLeft - from.BottomLeft) * animationProgress,
from.BottomRight + (to.BottomRight - from.BottomRight) * animationProgress);
}
public static Thickness GetThicknessValue(Thickness from, Thickness to, double animationProgress)
{
return new Thickness(
from.Left + (to.Left - from.Left) * animationProgress,
from.Top + (to.Top - from.Top) * animationProgress,
from.Right + (to.Right - from.Right) * animationProgress,
from.Bottom + (to.Bottom - from.Bottom) * animationProgress);
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
namespace MauiAnimation.Helpers
{
public static class EasingHelper
{
public static Easing GetEasing(EasingType type)
{
switch(type)
{
case EasingType.BounceIn:
return Easing.BounceIn;
case EasingType.BounceOut:
return Easing.BounceOut;
case EasingType.CubicIn:
return Easing.CubicIn;
case EasingType.CubicInOut:
return Easing.CubicInOut;
case EasingType.CubicOut:
return Easing.CubicOut;
case EasingType.Linear:
return Easing.Linear;
case EasingType.SinIn:
return Easing.SinIn;
case EasingType.SinInOut:
return Easing.SinInOut;
case EasingType.SinOut:
return Easing.SinOut;
case EasingType.SpringIn:
return Easing.SpringIn;
case EasingType.SpringOut:
return Easing.SpringOut;
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,71 @@
namespace MauiAnimation.Helpers
{
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public static class VisualTreeHelper
{
public static T GetParent<T>(this Element element) where T : Element
{
if (element is T)
{
return element as T;
}
else
{
if (element.Parent != null)
{
return element.Parent.GetParent<T>();
}
return default(T);
}
}
public static IEnumerable<T> GetChildren<T>(this Element element) where T : Element
{
var properties = element.GetType().GetRuntimeProperties();
var contentProperty = properties.FirstOrDefault(w => w.Name == "Content");
if (contentProperty != null)
{
if (contentProperty.GetValue(element) is Element content)
{
if (content is T)
{
yield return content as T;
}
foreach (var child in content.GetChildren<T>())
{
yield return child;
}
}
}
else
{
var childrenProperty = properties.FirstOrDefault(w => w.Name == "Children");
if (childrenProperty != null)
{
IEnumerable children = childrenProperty.GetValue(element) as IEnumerable;
foreach (var child in children)
{
if (child is Element childVisualElement)
{
if (childVisualElement is T)
{
yield return childVisualElement as T;
}
foreach (var childVisual in childVisualElement.GetChildren<T>())
{
yield return childVisual;
}
}
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>
<ItemGroup>
<Folder Include="Platforms\Android\" />
<Folder Include="Platforms\MacCatalyst\" />
<Folder Include="Platforms\Windows\" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,29 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
using MauiAnimation.Helpers;
public class AnimateColor : AnimationBaseTrigger<Color>
{
protected override async void Invoke(VisualElement sender)
{
if (TargetProperty == null)
{
throw new NullReferenceException("Null Target property.");
}
if (Delay > 0)
await Task.Delay(Delay);
SetDefaultFrom((Color)sender.GetValue(TargetProperty));
sender.Animate($"AnimateColor{TargetProperty.PropertyName}", new Animation((progress) =>
{
sender.SetValue(TargetProperty, AnimationHelper.GetColorValue(From, To, progress));
}),
length: Duration,
easing: EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
namespace MauiAnimation.Triggers
{
using System;
using System.Threading.Tasks;
using MauiAnimation.Helpers;
public class AnimateCornerRadius : AnimationBaseTrigger<CornerRadius>
{
protected override async void Invoke(VisualElement sender)
{
if (TargetProperty == null)
{
throw new NullReferenceException("Null Target property.");
}
if (Delay > 0)
await Task.Delay(Delay);
SetDefaultFrom((CornerRadius)sender.GetValue(TargetProperty));
sender.Animate($"AnimateCornerRadius{TargetProperty.PropertyName}", new Animation((progress) =>
{
sender.SetValue(TargetProperty, AnimationHelper.GetCornerRadiusValue(From, To, progress));
}),
length: Duration,
easing: EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
namespace MauiAnimation
{
using System;
using System.Threading.Tasks;
using MauiAnimation.Helpers;
public class AnimateDouble : AnimationBaseTrigger<double>
{
protected override async void Invoke(VisualElement sender)
{
if (TargetProperty == null)
{
throw new NullReferenceException("Null Target property.");
}
if (Delay > 0)
await Task.Delay(Delay);
SetDefaultFrom((double)sender.GetValue(TargetProperty));
sender.Animate($"AnimateDouble{TargetProperty.PropertyName}", new Animation((progress) =>
{
sender.SetValue(TargetProperty, AnimationHelper.GetDoubleValue(From, To, progress));
}),
length: Duration,
easing: EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
namespace MauiAnimation.Triggers
{
using System;
using System.Threading.Tasks;
using MauiAnimation.Helpers;
public class AnimateInt : AnimationBaseTrigger<double>
{
protected override async void Invoke(VisualElement sender)
{
if (TargetProperty == null)
{
throw new NullReferenceException("Null Target property.");
}
if (Delay > 0)
await Task.Delay(Delay);
SetDefaultFrom((double)sender.GetValue(TargetProperty));
sender.Animate($"AnimateInt{TargetProperty.PropertyName}", new Animation((progress) =>
{
sender.SetValue(TargetProperty, AnimationHelper.GetIntValue((int)From, (int)To, progress));
}),
length: Duration,
easing: EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
namespace MauiAnimation.Triggers
{
using System;
using System.Threading.Tasks;
using MauiAnimation.Helpers;
public class AnimateThickness : AnimationBaseTrigger<Thickness>
{
protected override async void Invoke(VisualElement sender)
{
if (TargetProperty == null)
{
throw new NullReferenceException("Null Target property.");
}
if (Delay > 0)
await Task.Delay(Delay);
SetDefaultFrom((double)sender.GetValue(TargetProperty));
sender.Animate($"AnimateThickness{TargetProperty.PropertyName}", new Animation((progress) =>
{
sender.SetValue(TargetProperty, AnimationHelper.GetThicknessValue(From, To, progress));
}),
length: Duration,
easing: EasingHelper.GetEasing(Easing));
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
namespace MauiAnimation
{
using System;
public abstract class AnimationBaseTrigger<T> : TriggerAction<VisualElement>
{
public T From { get; set; } = default(T);
public T To { get; set; } = default(T);
public uint Duration { get; set; } = 1000;
public int Delay { get; set; } = 0;
public EasingType Easing { get; set; } = EasingType.Linear;
public BindableProperty TargetProperty { get; set; } = default(BindableProperty);
protected override void Invoke(VisualElement sender)
{
throw new NotImplementedException("Please Implement Invoke() in derived-class");
}
protected void SetDefaultFrom(T property)
{
From = (From == null || From.Equals(default(T))) ? property : From;
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
namespace MauiAnimation
{
[ContentProperty("Animation")]
public class BeginAnimation : TriggerAction<VisualElement>
{
public AnimationBase Animation { get; set; }
protected override async void Invoke(VisualElement sender)
{
if (Animation != null)
await Animation.Begin();
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
namespace MauiAnimation
{
public class EndAnimation : TriggerAction<VisualElement>
{
public AnimationBase Animation { get; set; }
protected override void Invoke(VisualElement sender)
{
if (Animation != null)
Animation.End();
}
}
}