Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/shared element transition animation #26

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/java/com/trendyol/medusa/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class MainActivity : AppCompatActivity(), Navigator.NavigatorListener {
R.id.fragmentContainer,
rootFragmentProvider,
navigatorListener = this,
navigatorConfiguration = NavigatorConfiguration(1, true, NavigatorTransaction.SHOW_HIDE))
navigatorConfiguration = NavigatorConfiguration(1, true, NavigatorTransaction.SHOW_HIDE),
transitionAnimationType = TransitionAnimationType.RIGHT_TO_LEFT)

private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/trendyol/medusa/MainActivity2.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
rootsFragmentProvider,
this,
new NavigatorConfiguration(1, true, NavigatorTransaction.SHOW_HIDE),
null);
TransitionAnimationType.RIGHT_TO_LEFT);

multipleStackNavigator.initialize(savedInstanceState);
final SwitchCompat restartRootFragmentCheckBox = findViewById(R.id.restartSwitch);
Expand Down
11 changes: 10 additions & 1 deletion app/src/main/java/com/trendyol/medusa/SampleFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.trendyol.medusalib.navigator.transitionanimation.SharedElement
import com.trendyol.medusalib.navigator.transitionanimation.TransitionAnimationType
import kotlin.random.Random

Expand All @@ -19,9 +21,16 @@ class SampleFragment : BaseFragment() {

view.findViewById<LinearLayout>(R.id.root).setBackgroundColor(Color.argb(255, Random.nextInt(256), Random.nextInt(256), Random.nextInt(256)))

//Using for shared element transition
val image = view.findViewById<ImageView>(R.id.ic_android)
view.findViewById<Button>(R.id.button).setOnClickListener {
multipleStackNavigator!!.start(FragmentGenerator.generateNewFragment(), TransitionAnimationType.RIGHT_TO_LEFT)
multipleStackNavigator!!.start(SharedElementSampleSecondFragment.newInstance(), SharedElement(image))
}

//Default start fragment
/*view.findViewById<Button>(R.id.button).setOnClickListener {
multipleStackNavigator!!.start(FragmentGenerator.generateNewFragment())
}*/
return view
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.trendyol.medusa

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

class SharedElementSampleSecondFragment : BaseFragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {

val view = inflater.inflate(R.layout.fragment_second, container, false)!!

return view
}

companion object {
fun newInstance(): SharedElementSampleSecondFragment {
return SharedElementSampleSecondFragment()
}
}
}
8 changes: 8 additions & 0 deletions app/src/main/res/layout/fragment_sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@
android:layout_height="wrap_content"
android:text="start another"/>

<ImageView
android:layout_marginTop="200dp"
android:id="@+id/ic_android"
android:transitionName="logoTransitionName"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@android:mipmap/sym_def_app_icon" />

</LinearLayout>
17 changes: 17 additions & 0 deletions app/src/main/res/layout/fragment_second.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".SharedElementSampleSecondFragment">

<ImageView
android:id="@+id/ic_android"
android:transitionName="logoTransitionName"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@android:mipmap/sym_def_app_icon" />

</RelativeLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.trendyol.medusalib.navigator.data.FragmentData
import com.trendyol.medusalib.navigator.data.StackItem
import com.trendyol.medusalib.navigator.tag.TagCreator
import com.trendyol.medusalib.navigator.tag.UniqueTagCreator
import com.trendyol.medusalib.navigator.transitionanimation.SharedElement
import com.trendyol.medusalib.navigator.transitionanimation.TransitionAnimationType

open class MultipleStackNavigator(
Expand Down Expand Up @@ -52,6 +53,31 @@ open class MultipleStackNavigator(
start(fragment, DEFAULT_GROUP_NAME, transitionAnimation)
}

override fun start(fragment: Fragment, sharedElement: SharedElement) {
val createdTag = tagCreator.create(fragment)
val currentTabIndex = fragmentStackState.getSelectedTabIndex()
val fragmentData = FragmentData(fragment = fragment, fragmentTag = createdTag, sharedElement = sharedElement)

if (fragmentStackState.isSelectedTabEmpty()) {
val rootFragment = getRootFragment(currentTabIndex)
val rootFragmentTag = tagCreator.create(rootFragment)
val rootFragmentData = FragmentData(rootFragment, rootFragmentTag)
fragmentManagerController.disableAndStartFragment(
getCurrentFragmentTag(),
rootFragmentData,
fragmentData
)
} else {
fragmentManagerController.disableAndStartFragment(getCurrentFragmentTag(), fragmentData)
}
fragmentStackState.addStackItemToSelectedTab(
StackItem(
fragmentTag = createdTag,
groupName = DEFAULT_GROUP_NAME
)
)
}

override fun start(fragment: Fragment, fragmentGroupName: String, transitionAnimation: TransitionAnimationType?) {

val createdTag = tagCreator.create(fragment)
Expand Down Expand Up @@ -184,8 +210,7 @@ open class MultipleStackNavigator(
override fun initialize(savedState: Bundle?) {
if (savedState == null) {
initializeStackState()
}
else {
} else {
loadStackStateFromSavedState(savedState)
}
}
Expand Down Expand Up @@ -221,7 +246,7 @@ open class MultipleStackNavigator(

private fun getRootFragment(tabIndex: Int): Fragment =
fragmentManagerController.getFragment(fragmentStackState.peekItem(tabIndex).fragmentTag)
?: rootFragmentProvider.get(tabIndex).invoke()
?: rootFragmentProvider.get(tabIndex).invoke()

private fun showUpperFragment() {
val upperFragmentTag = fragmentStackState.peekItemFromSelectedTab().fragmentTag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.trendyol.medusalib.navigator
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.trendyol.medusalib.navigator.transaction.NavigatorTransaction
import com.trendyol.medusalib.navigator.transitionanimation.SharedElement
import com.trendyol.medusalib.navigator.transitionanimation.TransitionAnimationType

interface Navigator {
Expand Down Expand Up @@ -68,6 +69,16 @@ interface Navigator {
*/
fun start(fragment: Fragment, transitionAnimation: TransitionAnimationType)

/**
* Adds new fragment to the fragment stack with given tab index.
* Hide currently active fragment, switches to given tab Index
* and show newly added fragment to the user.
* @param fragment new fragment
* @param sharedElement will be used start fragment shared element transition animation
* all fragments which has the same group name.
*/
fun start(fragment: Fragment, sharedElement: SharedElement)

/**
* Modifies fragment stack. Pops current fragment from
* fragment stack and detaches it. Peeks from fragment stack
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.trendyol.medusalib.navigator.controller

import android.os.Build
import android.transition.TransitionInflater
import androidx.annotation.AnimRes
import androidx.annotation.AnimatorRes
import androidx.fragment.app.Fragment
Expand Down Expand Up @@ -80,18 +82,17 @@ class FragmentManagerController(private val fragmentManager: FragmentManager,
checkAndCreateTransaction()

for (fragmentData in fragmentDataArgs) {
currentTransitionAnimationType = fragmentData.transitionAnimation
when (currentTransitionAnimationType) {
TransitionAnimationType.LEFT_TO_RIGHT -> setCustomAnimations(R.anim.enter_from_left, R.anim.empty_animation)
TransitionAnimationType.RIGHT_TO_LEFT -> setCustomAnimations(R.anim.enter_from_right, R.anim.empty_animation)
TransitionAnimationType.BOTTOM_TO_TOP -> setCustomAnimations(R.anim.enter_from_bottom, R.anim.empty_animation)
TransitionAnimationType.TOP_TO_BOTTOM -> setCustomAnimations(R.anim.enter_from_top, R.anim.empty_animation)
TransitionAnimationType.FADE_IN_OUT -> setCustomAnimations(R.anim.fade_in, R.anim.empty_animation)
if (hasSharedElement(fragmentData)) {
setSharedElementTransitionAnimation(fragmentData, disabledFragment)
currentTransaction?.replace(containerId, fragmentData.fragment, fragmentData.fragmentTag)
} else {
setTransitionAnimation(fragmentData)
currentTransaction?.replace(containerId, fragmentData.fragment, fragmentData.fragmentTag)
}
currentTransaction?.add(containerId, fragmentData.fragment, fragmentData.fragmentTag)
}

val disabledFragmentNavigatorTransaction = getFragmentNavigatorTransaction(disableFragmentTag)

when (disabledFragmentNavigatorTransaction.transactionType) {
TransactionType.SHOW_HIDE -> currentTransaction?.hide(disabledFragment)
TransactionType.ATTACH_DETACH -> currentTransaction?.detach(disabledFragment)
Expand All @@ -100,6 +101,27 @@ class FragmentManagerController(private val fragmentManager: FragmentManager,
commitAllowingStateLoss()
}

private fun hasSharedElement(fragmentData: FragmentData) = fragmentData.sharedElement != null

private fun setSharedElementTransitionAnimation(fragmentData: FragmentData, disabledFragment: Fragment?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val view = fragmentData.sharedElement!!.view
currentTransaction?.addSharedElement(view, view.transitionName)
fragmentData.fragment.sharedElementEnterTransition = TransitionInflater.from(disabledFragment?.context).inflateTransition(android.R.transition.move)
}
}

private fun setTransitionAnimation(fragmentData: FragmentData) {
currentTransitionAnimationType = fragmentData.transitionAnimation
when (currentTransitionAnimationType) {
TransitionAnimationType.LEFT_TO_RIGHT -> setCustomAnimations(R.anim.enter_from_left, R.anim.empty_animation)
TransitionAnimationType.RIGHT_TO_LEFT -> setCustomAnimations(R.anim.enter_from_right, R.anim.empty_animation)
TransitionAnimationType.BOTTOM_TO_TOP -> setCustomAnimations(R.anim.enter_from_bottom, R.anim.empty_animation)
TransitionAnimationType.TOP_TO_BOTTOM -> setCustomAnimations(R.anim.enter_from_top, R.anim.empty_animation)
TransitionAnimationType.FADE_IN_OUT -> setCustomAnimations(R.anim.fade_in, R.anim.empty_animation)
}
}

private fun setCustomAnimations(@AnimatorRes @AnimRes enter: Int, @AnimatorRes @AnimRes exit: Int) {
currentTransaction?.setCustomAnimations(enter, exit)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.trendyol.medusalib.navigator.data

import androidx.fragment.app.Fragment
import com.trendyol.medusalib.navigator.transitionanimation.SharedElement
import com.trendyol.medusalib.navigator.transitionanimation.TransitionAnimationType

data class FragmentData(val fragment: Fragment, val fragmentTag: String, val transitionAnimation: TransitionAnimationType? = null)
data class FragmentData(val fragment: Fragment, val fragmentTag: String, val transitionAnimation: TransitionAnimationType? = null,
val sharedElement: SharedElement? = null)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.trendyol.medusalib.navigator.transitionanimation

import android.view.View

data class SharedElement(val view:View)