Skip to content

Commit cc59441

Browse files
fix: custom transitions
1 parent d09c435 commit cc59441

16 files changed

+164
-188
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ objects that are not shared in both fragments.
317317
of ***Transition*** start and end point to same value.
318318

319319
#### Note:
320-
🔥🔥🔥 In tutorial 2-4 and 2-5, having same background color for both fragments causing second fragment's enter transition(CircularReveal and Slide.BOTTOM) to not work
321-
So when using **Transitions** that extends ```Visiblity``` class such as Slide, or Fade be careful about background color
320+
🔥🔥🔥 In tutorial 2-4 and 2-5, having same background color for both fragments causing second fragment's **ENTER TRANSITION(CircularReveal and Slide.BOTTOM)** to not work
321+
So when using **Transitions** that extend ```Visiblity``` class such as Slide, or Fade be careful about background color.
322322
Either set callback and set start and end properties for scene with
323323

324324
```
@@ -359,6 +359,14 @@ visibility is changed from ```View.INVISIBLE``` to ```View.VISIBLE``` ```onAppea
359359
opposite ```onDisappear``` method is called. With scene's actual visibility change, or manual visibility change it's possible to play transitions
360360
from backwards.
361361

362+
### ‼️ Attention
363+
I wasn't able to create exit and return transitions using custom transitions with classes neither
364+
extend ```Transition``` nor ```Visibility```. Transitions such as Fade, Slide or Explode
365+
that extend ```Visibility``` work, but when i extend ```Visibility``` and do some custom transitions
366+
it does not work for **exitTransition** for first, **returnTransition** for second fragment.
367+
368+
If you figure out a solution feel free to send a PR🤩😍
369+
362370
### Resources and References
363371

364372
[CodeLab Property Animation](https://codelabs.developers.google.com/codelabs/advanced-android-kotlin-training-property-animation/#0)

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/chapter2_fragment_transitions/Fragment2_2LifeCycleFirst.kt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.smarttoolfactory.tutorial3_1transitions.chapter2_fragment_transition
22

33
import android.graphics.Color
44
import android.os.Bundle
5-
import android.view.Gravity
65
import android.view.LayoutInflater
76
import android.view.View
87
import android.view.ViewGroup
@@ -13,10 +12,11 @@ import androidx.constraintlayout.widget.ConstraintLayout
1312
import androidx.core.app.SharedElementCallback
1413
import androidx.fragment.app.Fragment
1514
import androidx.fragment.app.activityViewModels
16-
import androidx.transition.Slide
15+
import androidx.transition.Fade
1716
import androidx.transition.Transition
1817
import androidx.transition.TransitionSet
1918
import com.smarttoolfactory.tutorial3_1transitions.R
19+
import com.smarttoolfactory.tutorial3_1transitions.transition.ScaleTransition
2020
import com.smarttoolfactory.tutorial3_1transitions.transition.TextColorTransition
2121
import com.smarttoolfactory.tutorial3_1transitions.transition.TransitionXAdapter
2222

@@ -64,21 +64,31 @@ class Fragment2_2LifeCycleFirst : Fragment() {
6464
allowReturnTransitionOverlap = false
6565

6666

67-
val slide = Slide(Gravity.TOP)
67+
val slide = Fade()
6868
.apply {
69-
duration = 2000
69+
duration = 30
70+
startDelay = 470
7071
}
7172
val transitionSet = TransitionSet()
7273

7374
val textTransition =
7475
TextColorTransition(tvEnterTransition.currentTextColor, Color.MAGENTA, true)
7576
.apply {
7677
addTarget(tvExitTransition)
77-
duration = 800
78+
debugMode = true
79+
duration = 500
7880
}
7981

82+
val scaleTransition = ScaleTransition(1f, 1f, 0.95f, 0.95f, true)
83+
.apply {
84+
addTarget(view)
85+
debugMode = true
86+
duration = 500
87+
}
88+
8089
transitionSet.addTransition(slide)
8190
transitionSet.addTransition(textTransition)
91+
transitionSet.addTransition(scaleTransition)
8292

8393
exitTransition = transitionSet
8494

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/chapter2_fragment_transitions/Fragment2_5ToolbarDetail.kt

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ import com.smarttoolfactory.tutorial3_1transitions.adapter.model.PostCardModel
2626
import com.smarttoolfactory.tutorial3_1transitions.adapter.viewholder.ItemBinder
2727
import com.smarttoolfactory.tutorial3_1transitions.adapter.viewholder.PostCardViewBinder
2828
import com.smarttoolfactory.tutorial3_1transitions.transition.visibility.ForcedCircularReveal
29-
import com.smarttoolfactory.tutorial3_1transitions.transition.RotationTransition
29+
import com.smarttoolfactory.tutorial3_1transitions.transition.visibility.ForcedSlide
3030
import java.util.*
3131
import kotlin.collections.ArrayList
3232
import kotlin.math.hypot
3333

3434
/**
35-
* This sample uses custom transitions to overcome visiblity change issue that
36-
* causing transitions to not work
35+
* This sample uses custom transitions to overcome change issue that
36+
* causing ENTER transitions to not work. Having different visibility before and after
37+
* ENTER transition solves the issue
3738
*/
3839
class Fragment2_5ToolbarDetail : Fragment() {
3940

@@ -72,7 +73,7 @@ class Fragment2_5ToolbarDetail : Fragment() {
7273

7374
private fun setUpSharedElementTransition(view: View) {
7475

75-
allowEnterTransitionOverlap = false
76+
// allowEnterTransitionOverlap = false
7677

7778
/*
7879
🔥 Set sharedElementReturnTransition, because both
@@ -98,29 +99,28 @@ class Fragment2_5ToolbarDetail : Fragment() {
9899
val recyclerView = view.findViewById<View>(R.id.recyclerView)
99100
val viewImageBackground: View = view.findViewById(R.id.viewImageBackground)
100101

102+
viewImageBackground.visibility = View.INVISIBLE
101103

102104
val transitionSetEnter = TransitionSet()
103105

104-
val slideFromBottom =
105-
RotationTransition(-360f, 0f, true)
106-
.apply {
107-
interpolator = AnimationUtils.loadInterpolator(
108-
requireContext(),
109-
android.R.interpolator.linear_out_slow_in
110-
)
111-
startDelay = 400
112-
duration = 600
113-
addTarget(recyclerView)
114-
debugMode = true
115-
}
116-
106+
val slideFromBottom = ForcedSlide(Gravity.BOTTOM, View.INVISIBLE, View.VISIBLE)
107+
.apply {
108+
interpolator = AnimationUtils.loadInterpolator(
109+
requireContext(),
110+
android.R.interpolator.linear_out_slow_in
111+
)
112+
startDelay = 400
113+
duration = 600
114+
addTarget(recyclerView)
115+
}
117116

118117
val endRadius = hypot(
119118
viewImageBackground.width.toDouble(),
120119
viewImageBackground.height.toDouble()
121120
).toFloat()
122121

123-
val circularReveal = ForcedCircularReveal(View.INVISIBLE, View.VISIBLE)
122+
123+
val circularReveal = ForcedCircularReveal(View.INVISIBLE, View.VISIBLE, true)
124124
.apply {
125125
addTarget(viewImageBackground)
126126
setStartRadius(0f)

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/chapter2_fragment_transitions/Fragment2_5ToolbarList.kt

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.os.Bundle
44
import android.view.LayoutInflater
55
import android.view.View
66
import android.view.ViewGroup
7-
import android.widget.Toast
87
import androidx.core.view.doOnPreDraw
98
import androidx.fragment.app.Fragment
109
import androidx.navigation.NavDirections
@@ -14,7 +13,6 @@ import androidx.recyclerview.widget.ConcatAdapter
1413
import androidx.recyclerview.widget.LinearLayoutManager
1514
import androidx.recyclerview.widget.RecyclerView
1615
import androidx.transition.Fade
17-
import androidx.transition.Transition
1816
import com.smarttoolfactory.tutorial3_1transitions.ImageData
1917
import com.smarttoolfactory.tutorial3_1transitions.R
2018
import com.smarttoolfactory.tutorial3_1transitions.adapter.SingleViewBinderListAdapter
@@ -25,7 +23,6 @@ import com.smarttoolfactory.tutorial3_1transitions.adapter.viewholder.HeaderView
2523
import com.smarttoolfactory.tutorial3_1transitions.adapter.viewholder.ItemBinder
2624
import com.smarttoolfactory.tutorial3_1transitions.adapter.viewholder.MagazineListViewViewBinder
2725
import com.smarttoolfactory.tutorial3_1transitions.databinding.ItemMagazineBinding
28-
import com.smarttoolfactory.tutorial3_1transitions.transition.TransitionXAdapter
2926

3027
/*
3128
🔥‼️ Added transition id to MagazineModel because giving same resource id as transition name to multiple
@@ -111,27 +108,27 @@ class Fragment2_5ToolbarList : Fragment() {
111108
addTarget(view)
112109
}
113110

114-
(exitTransition as? Transition)?.addListener(object : TransitionXAdapter() {
115-
116-
override fun onTransitionStart(transition: Transition) {
117-
super.onTransitionStart(transition)
118-
Toast.makeText(
119-
requireContext(),
120-
"EXIT onTransitionStart()",
121-
Toast.LENGTH_SHORT
122-
).show()
123-
}
124-
125-
override fun onTransitionEnd(transition: Transition) {
126-
127-
super.onTransitionEnd(transition)
128-
Toast.makeText(
129-
requireContext(),
130-
"EXIT onTransitionEnd time: $animationDuration",
131-
Toast.LENGTH_SHORT
132-
).show()
133-
}
134-
})
111+
// (exitTransition as? Transition)?.addListener(object : TransitionXAdapter() {
112+
//
113+
// override fun onTransitionStart(transition: Transition) {
114+
// super.onTransitionStart(transition)
115+
// Toast.makeText(
116+
// requireContext(),
117+
// "EXIT onTransitionStart()",
118+
// Toast.LENGTH_SHORT
119+
// ).show()
120+
// }
121+
//
122+
// override fun onTransitionEnd(transition: Transition) {
123+
//
124+
// super.onTransitionEnd(transition)
125+
// Toast.makeText(
126+
// requireContext(),
127+
// "EXIT onTransitionEnd time: $animationDuration",
128+
// Toast.LENGTH_SHORT
129+
// ).show()
130+
// }
131+
// })
135132

136133

137134
reenterTransition =

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/transition/AlphaForcedTransition.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import com.smarttoolfactory.tutorial3_1transitions.R
1919
* [captureEndValues] to be invoked with different set of values.
2020
*
2121
* * If starting scene and ending scene is equal in alpha this transition will not start because
22-
* [captureEndValues] will not capture anything.
22+
* [captureEndValues] will not capture anything other than start values.
2323
*
2424
*/
2525
class AlphaForcedTransition : Transition {

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/transition/BackgroundColorForcedTransition.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ import com.smarttoolfactory.tutorial3_1transitions.R
2222
* [captureEndValues] to be invoked with different set of values.
2323
*
2424
* * If starting scene and ending scene is equal in alpha this transition will not start because
25-
* [captureEndValues] will not capture anything.
25+
* [captureEndValues] will not capture anything other than start values.
2626
*
2727
* Background color transition that changes background color value of views from starting to ending values if they are
2828
* set on view in a scene. Scene is basically state of views in visibility and other properties.
2929
*
3030
* * If starting scene and ending scene has equal background color this transition will not start because
31-
* [captureEndValues] will not capture anything.
31+
* [captureEndValues] will not capture anything other than start values.
3232
*
3333
*/
3434

@@ -79,15 +79,15 @@ class BackgroundColorForcedTransition : Transition {
7979
println("Key: $key, value: $value")
8080
}
8181
}
82-
83-
if (forceValues) {
84-
transitionValues.view.setBackgroundColor(endColor)
85-
}
8682
}
8783

8884
// Capture the value of property for a target in the ending Scene.
8985
override fun captureEndValues(transitionValues: TransitionValues) {
9086

87+
if (forceValues) {
88+
transitionValues.view.setBackgroundColor(endColor)
89+
}
90+
9191
captureValues(transitionValues)
9292

9393
if (debugMode) {

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/transition/BackgroundColorTransition.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import com.smarttoolfactory.tutorial3_1transitions.R
1818
* set on view in a scene. Scene is basically state of views in visibility and other properties.
1919
*
2020
* * If starting scene and ending scene has equal background color this transition will not start because
21-
* [captureEndValues] will not capture anything.
21+
* [captureEndValues] will not capture anything other than start values.
2222
*
2323
* * If there are no values set on view in your code, set [forceValues] flag to
2424
* ***true*** and change [startColor] and [endColor] values

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/transition/RotationForcedTransition.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import com.smarttoolfactory.tutorial3_1transitions.R
1919
* [captureEndValues] to be invoked with different set of values.
2020
*
2121
* * If starting scene and ending scene is equal in alpha this transition will not start because
22-
* [captureEndValues] will not capture anything.
22+
* [captureEndValues] will not capture anything other than start values.
2323
*
2424
*/
2525
class RotationForcedTransition : Transition {
@@ -72,13 +72,15 @@ class RotationForcedTransition : Transition {
7272
}
7373
}
7474

75-
if (forceValues) {
76-
transitionValues.view.rotation = endRotation
77-
}
7875
}
7976

8077
// Capture the value of property for a target in the ending Scene.
8178
override fun captureEndValues(transitionValues: TransitionValues) {
79+
80+
if (forceValues) {
81+
transitionValues.view.rotation = endRotation
82+
}
83+
8284
captureValues(transitionValues)
8385

8486
if (debugMode) {

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/transition/ScaleForcedTransition.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import com.smarttoolfactory.tutorial3_1transitions.R
1919
* [captureEndValues] to be invoked with different set of values.
2020
*
2121
* * If starting scene and ending scene is equal in alpha this transition will not start because
22-
* [captureEndValues] will not capture anything.
22+
* [captureEndValues] will not capture anything other than start values.
2323
*
2424
*/
2525
class ScaleForcedTransition : Transition {
@@ -84,15 +84,16 @@ class ScaleForcedTransition : Transition {
8484
}
8585
}
8686

87-
if (forceValues) {
88-
transitionValues.view?.scaleX = endScaleX
89-
transitionValues.view?.scaleY = endScaleY
90-
}
87+
9188

9289
}
9390

9491
// Capture the value of property for a target in the ending Scene.
9592
override fun captureEndValues(transitionValues: TransitionValues) {
93+
if (forceValues) {
94+
transitionValues.view?.scaleX = endScaleX
95+
transitionValues.view?.scaleY = endScaleY
96+
}
9697

9798
captureValues(transitionValues)
9899

Tutorial3-1Transitions/src/main/java/com/smarttoolfactory/tutorial3_1transitions/transition/TextColorForcedTransition.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.smarttoolfactory.tutorial3_1transitions.R
2121
* [captureEndValues] to be invoked with different set of values.
2222
*
2323
* * If starting scene and ending scene is equal in alpha this transition will not start because
24-
* [captureEndValues] will not capture anything.
24+
* [captureEndValues] will not capture anything other than start values.
2525
*
2626
*/
2727
class TextColorForcedTransition : Transition {
@@ -71,16 +71,15 @@ class TextColorForcedTransition : Transition {
7171
println("Key: $key, value: $value")
7272
}
7373
}
74-
75-
if (forceValues) {
76-
(transitionValues.view as? TextView)?.setTextColor(endColor)
77-
}
78-
7974
}
8075

8176
// Capture the value of property for a target in the ending Scene.
8277
override fun captureEndValues(transitionValues: TransitionValues) {
8378

79+
if (forceValues) {
80+
(transitionValues.view as? TextView)?.setTextColor(endColor)
81+
}
82+
8483
captureValues(transitionValues)
8584

8685
if (debugMode) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.smarttoolfactory.tutorial3_1transitions.transition.visibility
2+
3+
import android.view.View
4+
import androidx.transition.TransitionValues
5+
import androidx.transition.Visibility
6+
7+
8+
class BaseVisibility(
9+
private val startVisibility: Int = View.VISIBLE,
10+
private val endVisibility: Int = View.INVISIBLE,
11+
private val forceVisibilityChange: Boolean = false
12+
) : Visibility() {
13+
14+
override fun captureStartValues(transitionValues: TransitionValues) {
15+
if (forceVisibilityChange) {
16+
transitionValues.view.visibility = startVisibility
17+
}
18+
super.captureStartValues(transitionValues)
19+
}
20+
21+
override fun captureEndValues(transitionValues: TransitionValues) {
22+
if (forceVisibilityChange) {
23+
transitionValues.view.visibility = endVisibility
24+
}
25+
super.captureEndValues(transitionValues)
26+
}
27+
}

0 commit comments

Comments
 (0)