Giter Site home page Giter Site logo

jorik041 / xamarin.plugin.sharedtransitions Goto Github PK

View Code? Open in Web Editor NEW

This project forked from giampaologabba/xamarin.plugin.sharedtransitions

0.0 0.0 0.0 8.69 MB

Shared Element Transitions between pages in Xamarin.Forms (IOS/Android)

License: MIT License

C# 100.00%

xamarin.plugin.sharedtransitions's Introduction

Xamarin.Plugin.SharedTransitions

Activate shared element transitions between pages in Xamarin.Forms (IOS/Android)

NuGet License

What is a shared element transition?

Shared element transitions are animations connecting common elements from one page to another.
A shared element transition determines how elements that are present in two pages transition between them. For example, an image that is displayed on both Page A and Page B, transitions from A to B when B becomes visible.

      

Setup

Platform Support

Platform Version
Xamarin.iOS iOS 9+
Xamarin.Android API 21+
Android X (Xamarin.Forms 4.5+) API 29

Please note:

The sample apps include everything you need to play with this plugin (standard pages, Tabbed, MasterDetail, Shell). Btw, I recommend to read all this page, expecially the few Android limitations.

Usage

To activate transitions between pages, use the SharedTransitionNavigationPage instead of the classic NavigationPage:

MainPage = new SharedTransitionNavigationPage(new Page1());

Add the xmlns namespace in your pages:

xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"

Shell

Starting from 2.1 you can use shared transitions in shell too, just change the standard main Shell in AppShell.xaml to SharedTransitionShell, for example:

<sharedTransitions:SharedTransitionShell xmlns="http://xamarin.com/schemas/2014/forms" 
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
       Title="TransitionShellApp"
       x:Class="TransitionShellApp.AppShell">

    <!-- Your Pages -->
    <TabBar>
        ....
    </TabBar>
</sharedTransitions:SharedTransitionShell>

Dont forget to update the AppShell.xaml.cs:

using Plugin.SharedTransitions;

namespace TransitionShellApp
{
	public partial class AppShell : SharedTransitionShell
	{
		public AppShell()
		{
			InitializeComponent();
		}
	}
}

Now you can navigate inside each ShellContent using shared transitions, just follow the instructions below!

Basic shared transitions with fixed elements

This is the most basic type of transition. We are going to animate one or more views from Page1 to Page2.

Tag the views to transition in the source page (Page1):

<Image Source="mydog.jpg" sharedTransitions:Transition.Name="dogtransition" WidthRequest="100" />

Tag the views to transition in the destination page (Page2), using the same transition name:

<Image Source="mydog.jpg" sharedTransitions:Transition.Name="dogtransition"  WidthRequest="300" />

Now you can start the transition doing a standard push between pages:

 NavigationPage.Push(new Page2())

When doing a Pop from Page2 to Page1 a return transition will occour

Advanced shared transitions between collection of views and their details page

This type of shared transition is useful to animate a selected item from a collection of views (for example a listview or any custom control with bindable views) to his "details" page. To make this work we need to set the sharedTransitions:Transition.Group property. It can be a number or a string and MUST to be unique for every List Item.

Listview sample:

Bind the Transition.Group to a unique value in the source page . The Transition.Name property is used as usual to identify the views to transition.

<ListView Footer="" ItemsSource="{Binding Dogs}" HasUnevenRows="True" SelectionMode="None">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <Image Source="{Binding Image}" WidthRequest="100" Margin="0,8"
                            sharedTransitions:Transition.Name="DogImage"
                            sharedTransitions:Transition.Group="{Binding Id}"/>
                    <Label Text="{Binding Title}" VerticalOptions="Center" />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Then in the destination page, tag the views to transition. We dont have to specify the Transition Group in the destination page, the match between pages will occour with the Transition.Name property.

<StackLayout Spacing="20" Padding="10">
    <Image Source="{Binding SelectedDog.Image}" sharedTransitions:Transition.Name="DogImage"  />
    <Label Text="{Binding SelectedDog.Title}" HorizontalOptions="Center" FontAttributes="Bold" FontSize="Large" />
    <Label Text="{Binding SelectedDog.Description}" />
</StackLayout>

When navigating from the source listview page to the destination, you need to inform the NavigationPage of what Transition Group has been selected:

private async void MyItemTapped(object sender,  ItemTapEventArgs e)
{
   var tappedItemData = e.Item as MyModel;
  //this is required in order to pass the views to animate
   SharedTransitionNavigationPage.SetSelectedTransitionGroup(this, tappedItemData.Id);
   await Navigation.PushAsync(new Page3(tappedItemData));
}

Listview MVVM sample:

if you are using MVVM, you can bind the SelectedTransitionGroup property directly in XAML with binding:

<ContentPage 
    .....
    SharedTransitionNavigationPage.SelectedGroup={Binding Selectedgroup}

Then, in your VM valorize the SelectedGroup property before the push. Here a full example using the EventToCommandBehaviour from Prism (you can use whaterver you want to handle the tap in your viewmodel):

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True" Padding="0"
             xmlns:behaviors="http://prismlibrary.com"
             x:Class="TransitionApp.Views.DynamicSampleFrom" Title="Listview sample"
             sharedTransitions:SharedTransitionNavigationPage.TransitionSelectedGroup="{Binding SelectedDogId }" >

        <ListView Footer="" ItemsSource="{Binding Dogs}" HasUnevenRows="True" SelectionMode="None">
            <ListView.Behaviors>
                <behaviors:EventToCommandBehavior EventName="ItemTapped"
                                                  Command="{Binding NavigateDogCommand}" 
                                                  EventArgsParameterPath="Item" />
            </ListView.Behaviors>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal">
                            <Image Source="{Binding Image}" WidthRequest="100" Margin="0,8"
                                   sharedTransitions:Transition.Name="DogImage"
                                   sharedTransitions:Transition.Group="{Binding Id}"/>
                            <Label Text="{Binding Title}" VerticalOptions="Center" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
</ContentPage>

The ViewModel:

public class DynamicSampleFromViewModel : ViewModelBase
   {
       private List<DogModel> _dogs;
       public List<DogModel> Dogs
       {
           get { return _dogs; }
           set { SetProperty(ref _dogs, value); }
       }

       private int _selectedDogId;
       public int SelectedDogId
       {
           get { return _selectedDogId; }
           set { SetProperty(ref _selectedDogId, value); }
       }

       public DelegateCommand<DogModel> NavigateDogCommand { get; set; }

       public DynamicSampleFromViewModel(INavigationService navigationService) : base(navigationService)
       {
           NavigateDogCommand = new DelegateCommand<DogModel>(async (selectedDog) =>
           {
              SelectedDogId = selectedDog.Id;
              
              var navParam = new NavigationParameters {{nameof(selectedDog), selectedDog}}; 
              await navigationService.NavigateAsync($"{nameof(DynamicSampleTo)}",navParam);
           });
       }

       public override void OnNavigatedTo(INavigationParameters parameters)
       {
           base.OnNavigatedTo(parameters);

           if (parameters.GetNavigationMode() != NavigationMode.Back)
           {
               var description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
               Dogs = new List<DogModel>
               {
                   new DogModel {Id =1, Title = "Christmas Dog",    Image = "christmas_dog.jpg", Description = description},
                   new DogModel {Id =2, Title = "Cute Dog",         Image = "cute_dog.jpg",      Description = description},
                   new DogModel {Id =3, Title = "Lazy Dog",         Image = "lazy_dog.jpg",      Description = description},
                   new DogModel {Id =4, Title = "What the Dog??!?", Image = "what_the_dog.jpg",  Description = description},
               };
           }

       }
   }

Destination page

In the destination page, you have to just set the Transition Name property to display the animation:

<StackLayout Spacing="20" Padding="10">
    <Image Source="{Binding SelectedDog.Image}" sharedTransitions:Transition.Name="DogImage"  />
    <Label Text="{Binding SelectedDog.Title}" HorizontalOptions="Center" FontAttributes="Bold" FontSize="Large" />
    <Label Text="{Binding SelectedDog.Description}" />
</StackLayout>

Everything is in the sample apps, go take a look at it :)

Transition attached properties

Bindable property Description
Transition.Name The name of the transition used to associate viewvs between pages
Transition.Group The unique group used to associate transition groups in dynamic lists

SharedNavigationPage properties

Bindable property Description
SelectedTransitionGroup The selected Transition.Group used for dynamic transitions
SharedTransitionDuration Duration, in ms, of the shared transition
BackgroundAnimation Sets the background animation for this page. This is applied to also to all the views not included in the shared transition

Background animations provided:

Background animation Description
None Do not animate
Fade Show a fade animation
Flip Show a flip animation
SlideFromLeft Show a slide from left animation
SlideFromRight Show a slide from right animation
SlideFromTop Show a slide from top animation
SlideFromBottom Show a slide from bottom animation

Important notes

  • The sharedTransitions:Transition.Name in source and destination page needs to match in order to display the animated transition
  • You can animate multiple views at once, just remember that every Transition Name in a page needs to be unique
  • You can animate the same element in multiple, subsequent pages

iOS Notes

  • Full shape layout transition is supported (eg: different corner radius between starting and ending views)
  • You can pop the page using a PanGesture on the left side of the screen

Android X:

To enable AndroidX support, use Xamarin.Forms 4.5+ and target API 29.

Android Limitations

  • TabbedPage inside MasterDetailPage is not currently supported
  • When animating layouts (frame, stacklayouts....) i suggest to dont use a background transition other than "Fade" (or "None"). Android doesnt play well with background animation + shared transitions of layouts
  • Shape layout transitions are not well supported (they play well only on pushing Frames). I suppose there is some problem with clipping, maybe we can adjust this making a custom SharedTransition callback and play with shapes & clip, but i didnt find yet a way to do this (playng with shapes & clip i mean, create a custom callback is easy). IF anyone want to help it will be SUPER-welcome!

New Sample apps!

The sample apps have been completely rewritten: you can find examples for images & layouts, as well as dynamic examples (for both listview with DataTemplateSelector & collectionview). Every example is available in standard pages, tabbed, master detail and shell.

The main app is made with Prism and it sports the superawesome PancakeView and FFImageLoading plugins!

Note: Yes my dog is supercute and deserve her sample app :D

Roadmap

  • Improve Android shape transitions (different corner radius)

Latest release notes

2.2

  • AndroidX support (issues #23
  • Fix IOS "Failed to lookup the required marshalling information" (issue #31)
  • Fix Tabbed page inside MasterDetail (issue #30)
  • Fontsize transition for label in iOS
  • Improve Flip background animation in iOS
  • Improve transition in iOS removing occasional flickering
  • TransitionStack improvement using Weakdelegates

2.1

  • Shell support (issues #16, #17, #18)
  • Tabbed page support (issue #13)
  • Master Detail page support (issue #21)
  • Fix DataTemplate in ListView (issue #14)
  • Improved sample apps (more demos for MasterDetail, TabbedPage & Shell)
  • Code improvement & refactoring for better performance & stability
  • Xamarin.Forms 4.3+ is required

2.0.2

  • Fix issue #10 (crash in iOS with non-existant image)
  • Fix issue #11 (backward transition duration in iOS)
  • Fix Android backward transition duration

2.0.1

  • BREAKING: Properties renamed to: Transition.Name, Transition.Group and TransitionDuration
  • Full MVVM support with TransitionSelectedGroup
  • New, improved Transition management under the hood (no more limitation to int number for transition names & groups, faster view lookup for transitions)
  • New transition engine for ios (support for shape transitions, including boxview, images with different bounds, aspect ratios, ecc..)
  • New sample app in full MVVM with listview, collectionview and normal transitions (including demostrations with PancakeView and FFImageLoading)
  • Everything mostly rewritten fro the ground-up: better stability and functionality
  • Improved code comments and error handling
  • Added useful notes in code to help contributors to make this plugin better!

Copyright and license

Code released under the MIT license, see license file.

xamarin.plugin.sharedtransitions's People

Contributors

giampaologabba avatar jsuarezruiz avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.