Skip to content

Commit 78133fe

Browse files
author
chetan-fueled
committed
feat(*): transition for shared elements
1 parent a48f5a5 commit 78133fe

File tree

8 files changed

+267
-9
lines changed

8 files changed

+267
-9
lines changed

flowr/src/main/java/com/fueled/flowr/Flowr.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import android.content.Intent;
44
import android.content.pm.ActivityInfo;
55
import android.net.Uri;
6+
import android.os.Build;
67
import android.os.Bundle;
78
import android.support.annotation.AnimRes;
89
import android.support.annotation.IdRes;
910
import android.support.annotation.NonNull;
1011
import android.support.annotation.Nullable;
12+
import android.support.annotation.RequiresApi;
1113
import android.support.v4.app.Fragment;
1214
import android.support.v4.app.FragmentManager;
1315
import android.support.v4.app.FragmentTransaction;
@@ -18,6 +20,7 @@
1820
import com.fueled.flowr.internal.FlowrDeepLinkHandler;
1921
import com.fueled.flowr.internal.FlowrDeepLinkInfo;
2022
import com.fueled.flowr.internal.TransactionData;
23+
import com.fueled.flowr.internal.TransitionConfig;
2124

2225
import java.util.ArrayList;
2326
import java.util.Collections;
@@ -273,6 +276,10 @@ protected <T extends Fragment & FlowrFragment> int displayFragment(TransactionDa
273276
Fragment fragment = data.getFragmentClass().newInstance();
274277
fragment.setArguments(data.getArgs());
275278

279+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && data.getTransitionConfig() != null) {
280+
setTransitions(fragment, data.getTransitionConfig());
281+
}
282+
276283
FragmentTransaction transaction = screen.getScreenFragmentManager().beginTransaction();
277284

278285
if (!data.isSkipBackStack()) {
@@ -288,6 +295,11 @@ protected <T extends Fragment & FlowrFragment> int displayFragment(TransactionDa
288295
transaction.add(mainContainerId, fragment);
289296
}
290297

298+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && data.getTransitionConfig() != null &&
299+
data.getSharedElements() != null && data.getSharedElements().length > 0) {
300+
addSharedElements(transaction, data.getSharedElements());
301+
}
302+
291303
identifier = transaction.commit();
292304

293305
if (data.isSkipBackStack()) {
@@ -329,6 +341,33 @@ private <T extends Fragment & FlowrFragment> void injectDeepLinkInfo(Transaction
329341
}
330342
}
331343

344+
/**
345+
* Set transitions to the destination fragment from @{@link TransitionConfig}.
346+
*
347+
* @param fragment The destination Fragment.
348+
* @param transitionConfig The transition configuration @{@link TransitionConfig}.
349+
*/
350+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
351+
private void setTransitions(Fragment fragment, TransitionConfig transitionConfig) {
352+
fragment.setEnterTransition(transitionConfig.enter);
353+
fragment.setSharedElementEnterTransition(transitionConfig.sharedElementEnter);
354+
fragment.setExitTransition(transitionConfig.exit);
355+
fragment.setSharedElementReturnTransition(transitionConfig.sharedElementExit);
356+
}
357+
358+
/**
359+
* Add shared elements to a Fragment Transaction.
360+
*
361+
* @param transaction The transaction that will.
362+
* @param views The shared elements.
363+
*/
364+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
365+
private void addSharedElements(FragmentTransaction transaction, View[] views) {
366+
for (View view : views) {
367+
transaction.addSharedElement(view, view.getTransitionName());
368+
}
369+
}
370+
332371
/**
333372
* Set a Custom Animation to a Fragment transaction
334373
*
@@ -771,6 +810,18 @@ public Builder setCustomTransactionAnimation(@AnimRes int enterAnim, @AnimRes in
771810

772811
}
773812

813+
/**
814+
* Set transition between fragments.
815+
*
816+
* @param transitionConfig builder class for configuring fragment transitions
817+
* @param sharedElements array of shared elements
818+
*/
819+
public Builder setTransition(TransitionConfig transitionConfig, View... sharedElements) {
820+
data.setTransitionConfig(transitionConfig);
821+
data.setSharedElements(sharedElements);
822+
return this;
823+
}
824+
774825
/**
775826
* Don't use any animations for this transaction
776827
*/

flowr/src/main/java/com/fueled/flowr/internal/TransactionData.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.os.Bundle;
55
import android.support.v4.app.Fragment;
66
import android.support.v4.app.FragmentTransaction;
7+
import android.view.View;
78

89
import com.fueled.flowr.FlowrFragment;
910

@@ -23,6 +24,8 @@ public final class TransactionData<T extends Fragment & FlowrFragment> {
2324
private int popEnterAnim;
2425
private int popExitAnim;
2526
private Intent deepLinkIntent;
27+
private View[] sharedElements;
28+
private TransitionConfig transitionConfig;
2629

2730
public TransactionData(Class<? extends T> fragmentClass) {
2831
this(fragmentClass, FragmentTransaction.TRANSIT_NONE, FragmentTransaction.TRANSIT_NONE);
@@ -121,4 +124,20 @@ public int getExitAnim() {
121124
public void setExitAnim(int exitAnim) {
122125
this.exitAnim = exitAnim;
123126
}
127+
128+
public View[] getSharedElements() {
129+
return sharedElements;
130+
}
131+
132+
public void setSharedElements(View[] sharedElements) {
133+
this.sharedElements = sharedElements;
134+
}
135+
136+
public TransitionConfig getTransitionConfig() {
137+
return transitionConfig;
138+
}
139+
140+
public void setTransitionConfig(TransitionConfig transitionConfig) {
141+
this.transitionConfig = transitionConfig;
142+
}
124143
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.fueled.flowr.internal;
2+
3+
import android.os.Build;
4+
import android.support.annotation.RequiresApi;
5+
import android.transition.ChangeBounds;
6+
import android.transition.Explode;
7+
import android.transition.Fade;
8+
import android.transition.Slide;
9+
import android.transition.Transition;
10+
import android.view.Gravity;
11+
12+
/**
13+
* Copyright (c) 2017 Fueled. All rights reserved.
14+
*
15+
* @author chetansachdeva on 21/11/17
16+
*/
17+
18+
public class TransitionConfig {
19+
20+
public Transition sharedElementEnter;
21+
public Transition sharedElementExit;
22+
public Transition enter;
23+
public Transition exit;
24+
25+
private TransitionConfig(Builder builder) {
26+
sharedElementEnter = builder.sharedElementEnter;
27+
sharedElementExit = builder.sharedElementExit;
28+
enter = builder.enter;
29+
exit = builder.exit;
30+
}
31+
32+
public static final class Builder {
33+
private Transition sharedElementEnter;
34+
private Transition sharedElementExit;
35+
private Transition enter;
36+
private Transition exit;
37+
38+
public Builder() {
39+
}
40+
41+
public Builder sharedElementEnter(Transition val) {
42+
sharedElementEnter = val;
43+
return this;
44+
}
45+
46+
public Builder sharedElementExit(Transition val) {
47+
sharedElementExit = val;
48+
return this;
49+
}
50+
51+
public Builder enter(Transition val) {
52+
enter = val;
53+
return this;
54+
}
55+
56+
public Builder exit(Transition val) {
57+
exit = val;
58+
return this;
59+
}
60+
61+
public TransitionConfig build() {
62+
return new TransitionConfig(this);
63+
}
64+
}
65+
66+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
67+
public static class Provider {
68+
public static Transition fade = new Fade();
69+
public static Transition explode = new Explode();
70+
public static Transition slideRight = new Slide(Gravity.RIGHT);
71+
public static Transition slideLeft = new Slide(Gravity.LEFT);
72+
public static Transition changeBounds = new ChangeBounds();
73+
}
74+
}

sample/src/main/java/com/fueled/flowr/sample/HomeFragment.java

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.fueled.flowr.sample;
22

33
import android.databinding.DataBindingUtil;
4-
import android.os.Bundle;
4+
import android.os.Build;
5+
import android.support.annotation.NonNull;
56
import android.view.View;
67
import android.widget.Toast;
78

89
import com.fueled.flowr.NavigationIconType;
10+
import com.fueled.flowr.internal.TransitionConfig;
911
import com.fueled.flowr.sample.core.AbstractFragment;
1012
import com.fueled.flowr.sample.databinding.FragmentHomeBinding;
1113

@@ -32,6 +34,7 @@ protected void setupView(View view) {
3234
binding.homeOpenViewButton.setOnClickListener(this);
3335
binding.homeOpenLinkButton.setOnClickListener(this);
3436
binding.homeOpenFirstButton.setOnClickListener(this);
37+
binding.homeOpenTransitionButton.setOnClickListener(this);
3538
}
3639

3740
@Override
@@ -46,14 +49,21 @@ public NavigationIconType getNavigationIconType() {
4649

4750
@Override
4851
public void onClick(View view) {
49-
if (view.getId() == R.id.home_open_view_button) {
50-
displayViewFragment();
51-
} else if (view.getId() == R.id.home_open_link_button) {
52-
displayLinkFragment();
53-
} else if (view.getId() == R.id.home_open_first_button) {
54-
displayFirstFragment();
55-
} else {
56-
52+
switch (view.getId()) {
53+
case R.id.home_open_view_button:
54+
displayViewFragment();
55+
break;
56+
case R.id.home_open_link_button:
57+
displayLinkFragment();
58+
break;
59+
case R.id.home_open_transition_button:
60+
displayTransitionFragment();
61+
break;
62+
case R.id.home_open_first_button:
63+
displayFirstFragment();
64+
break;
65+
default:
66+
break;
5767
}
5868
}
5969

@@ -83,4 +93,24 @@ protected void onFragmentResults(int requestCode, int resultCode, Bundle data) {
8393
Toast.makeText(getContext(), resultFromStack, Toast.LENGTH_SHORT).show();
8494
}
8595
}
96+
97+
private void displayTransitionFragment() {
98+
getFlowr().open("/transition")
99+
.replaceCurrentFragment(true)
100+
.setTransition(getTransitionConfig(), binding.flowrTextView)
101+
.displayFragment();
102+
}
103+
104+
@NonNull
105+
private TransitionConfig getTransitionConfig() {
106+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
107+
return new TransitionConfig.Builder()
108+
.sharedElementEnter(TransitionConfig.Provider.changeBounds)
109+
.sharedElementExit(TransitionConfig.Provider.changeBounds)
110+
.enter(TransitionConfig.Provider.fade)
111+
.exit(TransitionConfig.Provider.fade)
112+
.build();
113+
}
114+
return null;
115+
}
86116
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.fueled.flowr.sample;
2+
3+
import android.view.View;
4+
5+
import com.fueled.flowr.NavigationIconType;
6+
import com.fueled.flowr.annotations.DeepLink;
7+
import com.fueled.flowr.sample.core.AbstractFragment;
8+
9+
/**
10+
* Created by [email protected] on 18/05/2017.
11+
* Copyright (c) 2017 Fueled. All rights reserved.
12+
*/
13+
14+
@DeepLink(value = {"/transition"})
15+
public class TransitionFragment extends AbstractFragment {
16+
17+
@Override
18+
public int getLayoutId() {
19+
return R.layout.fragment_transition;
20+
}
21+
22+
@Override
23+
protected void setupView(View view) {
24+
25+
}
26+
27+
@Override
28+
public String getTitle() {
29+
return "Transition Fragment";
30+
}
31+
32+
@Override
33+
public NavigationIconType getNavigationIconType() {
34+
return NavigationIconType.HAMBURGER;
35+
}
36+
}

sample/src/main/res/layout/fragment_home.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,22 @@
99
android:gravity="center"
1010
android:orientation="vertical">
1111

12+
<TextView
13+
android:id="@+id/flowr_text_view"
14+
android:layout_width="wrap_content"
15+
android:layout_height="wrap_content"
16+
android:background="@color/colorPrimary"
17+
android:padding="4dp"
18+
android:text="@string/app_name"
19+
android:textColor="@color/white"
20+
android:textSize="16sp"
21+
android:transitionName="transitionText"/>
22+
1223
<Button
1324
android:id="@+id/home_open_view_button"
1425
android:layout_width="wrap_content"
1526
android:layout_height="wrap_content"
27+
android:layout_marginTop="10dp"
1628
android:text="@string/open_view_fragment"/>
1729

1830
<Button
@@ -29,6 +41,13 @@
2941
android:layout_marginTop="10dp"
3042
android:text="@string/open_first_fragment"/>
3143

44+
<Button
45+
android:id="@+id/home_open_transition_button"
46+
android:layout_width="wrap_content"
47+
android:layout_height="wrap_content"
48+
android:layout_marginTop="10dp"
49+
android:text="@string/open_transition_fragment"/>
50+
3251
</LinearLayout>
3352

3453
</layout>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent"
5+
android:background="#FFFFFF"
6+
android:orientation="vertical">
7+
8+
<TextView
9+
android:layout_width="wrap_content"
10+
android:layout_height="wrap_content"
11+
android:layout_gravity="center"
12+
android:text="@string/transition_message"/>
13+
14+
<TextView
15+
android:id="@+id/flowr_text_view"
16+
android:layout_width="wrap_content"
17+
android:layout_height="wrap_content"
18+
android:layout_gravity="center_horizontal"
19+
android:layout_marginTop="10dp"
20+
android:background="@color/colorPrimary"
21+
android:padding="8dp"
22+
android:text="@string/app_name"
23+
android:textColor="@color/white"
24+
android:textSize="20sp"
25+
android:transitionName="transitionText"/>
26+
27+
</FrameLayout>

0 commit comments

Comments
 (0)