1
0
Форкнуть 0
This commit is contained in:
Evolutionlab 2019-08-17 15:17:34 +02:00
Родитель 4a42a8c6d1
Коммит 4f38689127
6 изменённых файлов: 171 добавлений и 94 удалений

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

@ -1,5 +1,5 @@
## 2.0.0
* **Properties renamed to: Transition.Name, Transition.Group and TransitionDuration <-- BREAKING**
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 (supporting shape transitions, images with different bounds, aspect ratios, ecc..)

261
README.md
Просмотреть файл

@ -6,13 +6,11 @@ Activate shared element transitions between pages in Xamarin.Forms (IOS/Android)
#### What is a shared element transition?
Shared element transitions are animations connecting common elements from one page to the next/previous.<br>
Shared element transitions are animations connecting common elements from one page to another.<br>
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.
Transitions in apps provide visual continuity, connecting common elements from one page to the next.
<img src="images/transition_droid_new.gif" height="500">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="images/transition_ios_new.gif" height="500">
<img src="images/collectionview.gif" height="500">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="images/layouts.gif" height="500">
## Setup
@ -26,6 +24,14 @@ Transitions in apps provide visual continuity, connecting common elements from o
|Xamarin.iOS|iOS 9+|
|Xamarin.Android|API 21+|
## Please note:
Starting from version 2, attached properties have been renamed to: ```Transition.Name```, ```Transition.Group``` and ```TransitionDuration```.
**This is a Breaking change!**
The new [sample app](https://github.com/Evolutionlab/Xamarin.Plugin.SharedTransitions/tree/master/src/Sample/TransitionApp) will include everything you need to play with this plugin.
Btw, I recommend to read all this page, expecially the few Android limitations.
## Usage
@ -35,65 +41,69 @@ MainPage = new SharedTransitionNavigationPage(new Page1());
```
Add the xmlns namespace in your pages:
```
```xml
xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
```
#### Basic shared transitions with fixed elements
### 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**, for example *Page1.xaml*:
Tag the views to transition in the **source page** (Page1):
```xml
<Image Source="mydog.jpg" sharedTransitions:Transition.Name="dogtransition" WidthRequest="100" />
```
Tag the views to transition in the **destination page**, for example *Page2.xaml*:
Tag the views to transition in the **destination page** (Page2), using the same transition name:
```xml
<Image Source="mydog.jpg" sharedTransitions:Transition.Name="dogtransition" WidthRequest="300" />
```
Now from Page1 you can push Page2 to start the transition:
Now you can start the transition doing a standard push between pages:
```csharp
NavigationPage.Push(new Page2())
```
When doing a Pop prom Page2 to Page1 a return transition will occour
When doing a Pop from Page2 to Page1 a return transition will occour
#### Advanced shared transitions between collection of views and their details page
### 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.
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 in the **source page**, binding the Transition Group to a unique integer. The Transition Name property is used the same as the basic shared transition example.
#### 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.
```xml
<ListView HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name}" Font="18"/>
<Image Source="{Binding imgsource}"
HorizontalOptions="EndAndExpand"
HeightRequest="30" WidthRequest="50"
sharedTransitions:Transition.Name="test"
sharedTransitions:Transition.Group="{Binding Id}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<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>
```
Tag the views to transition in the **destination page**, for example *Page3.xaml*. We dont have to specify the Transition Group in the destination page, the match between pages will occour with the Transition Name property.
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.
```xml
<Image x:Name="detailImage" sharedTransitions:Transition.Name="test" WidthRequest="300" />
<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:
@ -108,97 +118,164 @@ When navigating from the source listview page to the destination, you need to in
}
```
if you are using MVVM, you can bind the SelectedTransitionGroup property directly in XAML with binding:
#### Listview MVVM sample:
if you are using MVVM, you can bind the ```SelectedTransitionGroup``` property directly in XAML with binding:
```xml
<ContentPage .....
.....
SharedTransitionNavigationPage.SelectedGroup={Binding Selectedgroup}
```
Then, in your VM valorize the SelectedGroup property before the push.
Then, in your VM valorize the ```SelectedGroup``` property before the push. Here a full example using the ```EventToCommandBehaviour``` from [Prism](https://github.com/PrismLibrary/Prism) (you can use whaterver you want to handle the tap in your viewmodel):
```xml
In the destination page, you have to just set the Transition Name property to display the animation.
<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 }" >
#### SharedNavigationPage methods
For every setter specified here, we have the corrisponding getter
```csharp
// Sets the selected tag group for this page
public static void SetSelectedTransitionGroup(Page page, int value)
// Sets the duration of the shared transition for this page (in ms).
public static void SetSharedTransitionDuration(Page page, long value)
// Sets the background animation for this page.
// This is applied to also to all the views not included in the shared transition
public static void SetBackgroundAnimation(Page page, BackgroundAnimation value)
<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>
```
Background animations provided:
**The ViewModel:**
```csharp
/// Background Animation Type
/// </summary>
public enum BackgroundAnimation
```csharp
public class DynamicSampleFromViewModel : ViewModelBase
{
/// <summary>
/// Do not animate.
/// </summary>
None = 0,
private List<DogModel> _dogs;
public List<DogModel> Dogs
{
get { return _dogs; }
set { SetProperty(ref _dogs, value); }
}
/// <summary>
/// Show a fade animation.
/// </summary>
Fade = 1,
private int _selectedDogId;
public int SelectedDogId
{
get { return _selectedDogId; }
set { SetProperty(ref _selectedDogId, value); }
}
/// <summary>
/// Show a flip animation.
/// </summary>
Flip = 2,
public DelegateCommand<DogModel> NavigateDogCommand { get; set; }
/// <summary>
/// Show a slide from left animation.
/// </summary>
SlideFromLeft = 3,
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);
});
}
/// <summary>
/// Show a slide from right animation.
/// </summary>
SlideFromRight = 4,
public override void OnNavigatedTo(INavigationParameters parameters)
{
base.OnNavigatedTo(parameters);
/// <summary>
/// Show a slide from top animation.
/// </summary>
SlideFromTop = 5,
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},
};
}
/// <summary>
/// Show a slide from bottom animation.
/// </summary>
SlideFromBottom = 6
}
}
}
```
## General notes
**Destination page**
In the destination page, you have to just set the Transition Name property to display the animation:
```xml
<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 app](https://github.com/Evolutionlab/Xamarin.Plugin.SharedTransitions/tree/master/src/Sample/TransitionApp), go take a look at it :)
## Transition attache 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
## 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 Limitations
* 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!
* The Collectionview has a strange behaviour: when popping to the first item, if the collectionview scroll is zero the transition has some minor glitch. If we make a small scroll (even 1 pixel) everything works fine. This happens ONLY in the first item and ONLY when the scroll is 0. I'm waiting for the final collectionview and if this will persists i'll make a simple customrenderer that will set the minscroll to 1
* 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!
* **The Collectionview has a strange behaviour:** when popping to the first item, if the collectionview scroll is zero the transition has some minor glitch. If we make a small scroll (even 1 pixel) everything works fine. This happens ONLY in the first item and ONLY when the scroll is 0. I'm waiting for the final collectionview and if this will persists i'll make a simple customrenderer that will set the minscroll to 1
## New Sample app!
The sample app has been completely rewritten: you can find simple examples (images & layouts) as well as dynamic examples (for both listview & collectionview).
Tha app is made with [Prism](https://github.com/PrismLibrary/Prism) and it sports the superawesome [PancakeView](https://github.com/sthewissen/Xamarin.Forms.PancakeView/) and [FFImageLoading](https://github.com/luberda-molinet/FFImageLoading) plugins
The sample app has been completely rewritten: you can find examples for images & layouts, as well as dynamic examples (for both listview & collectionview).
The app is made with [Prism](https://github.com/PrismLibrary/Prism) and it sports the superawesome [PancakeView](https://github.com/sthewissen/Xamarin.Forms.PancakeView/) and [FFImageLoading](https://github.com/luberda-molinet/FFImageLoading) plugins!
## More samples!
@ -217,8 +294,8 @@ Note: This sample use the old version of this plugin. That code will not work wi
## Latest release notes
2.0.0
* **Properties renamed to: Transition.Name, Transition.Group and TransitionDuration <-- BREAKING**
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 (supporting shape transitions, images with different bounds, aspect ratios, ecc..)

Двоичные данные
images/collectionview.gif Normal file

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

После

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

Двоичные данные
images/layouts.gif Normal file

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

После

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

Двоичные данные
images/transition_droid_new.gif

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

До

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

Двоичные данные
images/transition_ios_new.gif

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

До

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