diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt index 1ff213370..1358dda5d 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -19,12 +19,12 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProviders import androidx.navigation.Navigation +import androidx.transition.TransitionInflater import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.component_search.* import kotlinx.android.synthetic.main.fragment_browser.* import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.android.synthetic.main.fragment_search.* -import kotlinx.android.synthetic.main.layout_quick_action_sheet.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO @@ -116,6 +116,7 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + postponeEnterTransition() job = Job() } @@ -128,6 +129,7 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope { customTabSessionId = arguments?.getString(IntentProcessor.ACTIVE_SESSION_ID) val view = inflater.inflate(R.layout.fragment_browser, container, false) + view.browserLayout.transitionName = "$TAB_ITEM_TRANSITION_NAME${getSessionById()?.id}" toolbarComponent = ToolbarComponent( view.browserLayout, @@ -179,13 +181,13 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope { QuickActionViewModel::class.java ) { QuickActionViewModel( - QuickActionState( - readable = getSessionById()?.readerable ?: false, - bookmarked = findBookmarkedURL(getSessionById()), - readerActive = getSessionById()?.readerMode ?: false, - bounceNeeded = false + QuickActionState( + readable = getSessionById()?.readerable ?: false, + bookmarked = findBookmarkedURL(getSessionById()), + readerActive = getSessionById()?.readerMode ?: false, + bounceNeeded = false + ) ) - ) } ) @@ -206,6 +208,15 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + toolbarIntegration.set( + feature = (toolbarComponent.uiView as ToolbarUIView).toolbarIntegration, + owner = this, + view = view + ) + + sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move) + startPostponedEnterTransition() + val sessionManager = requireComponents.core.sessionManager contextMenuFeature.set( @@ -268,12 +279,6 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope { view = view ) - toolbarIntegration.set( - feature = (toolbarComponent.uiView as ToolbarUIView).toolbarIntegration, - owner = this, - view = view - ) - val accentHighContrastColor = DefaultThemeManager.resolveAttribute(R.attr.accentHighContrast, requireContext()) sitePermissionsFeature.set( @@ -771,6 +776,7 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope { } companion object { + private const val TAB_ITEM_TRANSITION_NAME = "tab_item" private const val REQUEST_CODE_DOWNLOAD_PERMISSIONS = 1 private const val REQUEST_CODE_PROMPT_PERMISSIONS = 2 private const val REQUEST_CODE_APP_PERMISSIONS = 3 diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt index 03f1f3e2b..74f379e08 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarIntegration.kt @@ -5,7 +5,10 @@ package org.mozilla.fenix.components.toolbar import android.content.Context +import android.view.ViewGroup +import androidx.navigation.NavOptions import androidx.navigation.Navigation +import androidx.navigation.fragment.FragmentNavigator import mozilla.components.browser.domains.autocomplete.DomainAutocompleteProvider import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.runWithSession @@ -19,13 +22,13 @@ import mozilla.components.support.base.feature.LifecycleAwareFeature import mozilla.components.support.ktx.android.view.hideKeyboard import org.mozilla.fenix.DefaultThemeManager import org.mozilla.fenix.R -import org.mozilla.fenix.browser.BrowserFragmentDirections import org.mozilla.fenix.ext.components import org.mozilla.fenix.utils.Settings class ToolbarIntegration( context: Context, toolbar: BrowserToolbar, + browserLayout: ViewGroup, toolbarMenu: ToolbarMenu, domainAutocompleteProvider: DomainAutocompleteProvider, historyStorage: HistoryStorage, @@ -53,8 +56,18 @@ class ToolbarIntegration( sessionManager, { toolbar.hideKeyboard() + // We need to dynamically add the options here because if you do it in XML it overwrites + val options = NavOptions.Builder().setPopUpTo(R.id.browserFragment, false) + .setEnterAnim(R.anim.fade_in).setExitAnim(R.anim.fade_out).build() + val extras = + FragmentNavigator.Extras.Builder() + .addSharedElement( + browserLayout, + "$TAB_ITEM_TRANSITION_NAME${sessionManager.selectedSession?.id}" + ) + .build() Navigation.findNavController(toolbar) - .navigate(BrowserFragmentDirections.actionBrowserFragmentToHomeFragment()) + .navigate(R.id.action_browserFragment_to_homeFragment, null, options, extras) }, isPrivate ) @@ -74,8 +87,10 @@ class ToolbarIntegration( toolbar, context.components.core.sessionManager, sessionId, - ToolbarFeature.UrlRenderConfiguration(PublicSuffixList(context), - DefaultThemeManager.resolveAttribute(R.attr.primaryText, context), renderStyle = renderStyle) + ToolbarFeature.UrlRenderConfiguration( + PublicSuffixList(context), + DefaultThemeManager.resolveAttribute(R.attr.primaryText, context), renderStyle = renderStyle + ) ) private var menuPresenter = MenuPresenter(toolbar, context.components.core.sessionManager, sessionId) @@ -88,4 +103,8 @@ class ToolbarIntegration( menuPresenter.stop() toolbarPresenter.stop() } + + companion object { + private const val TAB_ITEM_TRANSITION_NAME = "tab_item" + } } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarUIView.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarUIView.kt index cad790a37..59ad3d386 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarUIView.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarUIView.kt @@ -108,6 +108,7 @@ class ToolbarUIView( toolbarIntegration = ToolbarIntegration( this, view, + container, menuToolbar, ShippedDomainsProvider().also { it.initialize(this) }, components.core.historyStorage, diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index b3e6c7205..c730c5d40 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -19,6 +19,8 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.navigation.Navigation +import androidx.navigation.fragment.FragmentNavigator +import androidx.transition.TransitionInflater import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.view.* import kotlinx.coroutines.CoroutineScope @@ -46,6 +48,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.collections.CreateCollectionViewModel import org.mozilla.fenix.collections.SaveCollectionStep import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.allowUndo import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.urlToTrimmedHost @@ -96,6 +99,12 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + postponeEnterTransition() + sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -156,6 +165,13 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { } } + postponeEnterTransition() + sessionControlComponent.view.getViewTreeObserver() + .addOnPreDrawListener { + startPostponedEnterTransition() + true + } + view.menuButton.setOnClickListener { homeMenu?.menuBuilder?.build(requireContext())?.show( anchor = it, @@ -285,7 +301,12 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { val session = requireComponents.core.sessionManager.findSessionById(action.sessionId) requireComponents.core.sessionManager.select(session!!) - (activity as HomeActivity).openToBrowser(BrowserDirection.FromHome) + val directions = HomeFragmentDirections.actionHomeFragmentToBrowserFragment(null) + val extras = + FragmentNavigator.Extras.Builder() + .addSharedElement(action.tabView, "$TAB_ITEM_TRANSITION_NAME${action.sessionId}") + .build() + Navigation.findNavController(action.tabView).navigate(directions, extras) } is TabAction.Close -> { if (deleteSessionJob == null) removeTabWithUndo(action.sessionId) else { @@ -401,7 +422,8 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { (activity as HomeActivity).openToBrowserAndLoad( searchTermOrURL = action.tab.url, newTab = true, - from = BrowserDirection.FromHome) + from = BrowserDirection.FromHome + ) } is CollectionAction.OpenTabs -> { invokePendingDeleteJobs() @@ -662,6 +684,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { override fun onProfileUpdated(profile: Profile) { emitAccountChanges() } companion object { + private const val TAB_ITEM_TRANSITION_NAME = "tab_item" private const val toolbarPaddingDp = 12f private const val MOTION_LAYOUT_PROGRESS_ROUND_POINT = 0.25f } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt index ac097f8f5..b695b3f96 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.home.sessioncontrol import android.content.Context import android.graphics.Bitmap import android.os.Parcelable +import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import io.reactivex.Observer @@ -97,7 +98,7 @@ sealed class TabAction : Action { object Add : TabAction() object ShareTabs : TabAction() data class CloseAll(val private: Boolean) : TabAction() - data class Select(val sessionId: String) : TabAction() + data class Select(val tabView: View, val sessionId: String) : TabAction() data class Close(val sessionId: String) : TabAction() data class Share(val sessionId: String) : TabAction() object PrivateBrowsingLearnMore : TabAction() diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt index 2cd21bd36..3e3e02bc4 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabViewHolder.kt @@ -53,7 +53,7 @@ class TabViewHolder( close_tab_button.increaseTapArea(buttonIncreaseDps) item_tab.setOnClickListener { - actionEmitter.onNext(TabAction.Select(tab?.sessionId!!)) + actionEmitter.onNext(TabAction.Select(it, tab?.sessionId!!)) } item_tab.setOnLongClickListener { @@ -85,6 +85,7 @@ class TabViewHolder( fun bindSession(tab: Tab) { this.tab = tab updateTabUI(tab) + item_tab.transitionName = "$TAB_ITEM_TRANSITION_NAME${tab.sessionId}" updateSelected(tab.selected ?: false) } @@ -105,6 +106,7 @@ class TabViewHolder( } companion object { + private const val TAB_ITEM_TRANSITION_NAME = "tab_item" const val LAYOUT_ID = R.layout.tab_list_row const val buttonIncreaseDps = 12 const val favIconBorderRadiusInPx = 8 diff --git a/app/src/main/res/layout/component_session_control.xml b/app/src/main/res/layout/component_session_control.xml index 36941dea9..345c777f3 100644 --- a/app/src/main/res/layout/component_session_control.xml +++ b/app/src/main/res/layout/component_session_control.xml @@ -3,11 +3,12 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - \ No newline at end of file + android:transitionGroup="false" /> diff --git a/app/src/main/res/layout/fragment_browser.xml b/app/src/main/res/layout/fragment_browser.xml index e9c06b4b1..7d9f6e94b 100644 --- a/app/src/main/res/layout/fragment_browser.xml +++ b/app/src/main/res/layout/fragment_browser.xml @@ -24,7 +24,7 @@ android:clipToPadding="true" app:behavior_hideable="true" app:behavior_peekHeight="12dp" - app:layout_behavior="org.mozilla.fenix.quickactionsheet.QuickActionSheetBehavior"/> + app:layout_behavior="org.mozilla.fenix.quickactionsheet.QuickActionSheetBehavior" /> + android:visibility="gone" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index efe972332..6c4a134f2 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -13,6 +13,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="?homeBackground" + android:clipChildren="false" app:layoutDescription="@xml/home_scene" tools:context=".home.HomeFragment"> diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 9087109ec..ca0f7f89d 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -28,7 +28,9 @@ app:destination="@id/searchFragment" /> + app:destination="@id/browserFragment" + app:enterAnim="@anim/fade_in" + app:exitAnim="@anim/fade_out" /> @@ -113,9 +115,7 @@ tools:layout="@layout/fragment_browser"> + app:destination="@id/homeFragment" /> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9f36cc663..e70c78f96 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -6,6 +6,7 @@