For #6940: Fixes top dynamic toolbar behavior (#9900)

fennec/production
Sawyer Blatz 4 years ago committed by GitHub
parent 40550e88de
commit a8e624959e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -19,7 +19,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_browser.* import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.android.synthetic.main.fragment_browser.view.*
@ -77,6 +76,7 @@ import org.mozilla.fenix.components.toolbar.BrowserInteractor
import org.mozilla.fenix.components.toolbar.BrowserToolbarView import org.mozilla.fenix.components.toolbar.BrowserToolbarView
import org.mozilla.fenix.components.toolbar.BrowserToolbarViewInteractor import org.mozilla.fenix.components.toolbar.BrowserToolbarViewInteractor
import org.mozilla.fenix.components.toolbar.DefaultBrowserToolbarController import org.mozilla.fenix.components.toolbar.DefaultBrowserToolbarController
import org.mozilla.fenix.components.toolbar.SwipeRefreshScrollingViewBehavior
import org.mozilla.fenix.components.toolbar.ToolbarIntegration import org.mozilla.fenix.components.toolbar.ToolbarIntegration
import org.mozilla.fenix.downloads.DownloadNotificationBottomSheetDialog import org.mozilla.fenix.downloads.DownloadNotificationBottomSheetDialog
import org.mozilla.fenix.downloads.DownloadService import org.mozilla.fenix.downloads.DownloadService
@ -175,8 +175,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height) val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)
initializeEngineView(toolbarHeight)
browserAnimator = BrowserAnimator( browserAnimator = BrowserAnimator(
fragment = WeakReference(this), fragment = WeakReference(this),
engineView = WeakReference(engineView), engineView = WeakReference(engineView),
@ -510,6 +508,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
view = view view = view
) )
} }
initializeEngineView(toolbarHeight)
} }
} }
@ -520,7 +520,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
val behavior = if (requireContext().settings().shouldUseBottomToolbar) { val behavior = if (requireContext().settings().shouldUseBottomToolbar) {
EngineViewBottomBehavior(context, null) EngineViewBottomBehavior(context, null)
} else { } else {
AppBarLayout.ScrollingViewBehavior(context, null) SwipeRefreshScrollingViewBehavior(requireContext(), null, engineView, browserToolbarView)
} }
(swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior (swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior

@ -23,7 +23,6 @@ import mozilla.components.feature.session.TrackingProtectionUseCases
import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.feature.tabs.WindowFeature import mozilla.components.feature.tabs.WindowFeature
import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.FeatureFlags
@ -103,10 +102,6 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
owner = this, owner = this,
view = view view = view
) )
consumeFrom(browserFragmentStore) {
browserToolbarView.update(it)
}
} }
} }

@ -31,4 +31,8 @@ open class BrowserInteractor(
override fun onBrowserMenuDismissed(lowPrioHighlightItems: List<ToolbarMenu.Item>) { override fun onBrowserMenuDismissed(lowPrioHighlightItems: List<ToolbarMenu.Item>) {
browserToolbarController.handleBrowserMenuDismissed(lowPrioHighlightItems) browserToolbarController.handleBrowserMenuDismissed(lowPrioHighlightItems)
} }
override fun onScrolled(offset: Int) {
browserToolbarController.handleScroll(offset)
}
} }

@ -48,6 +48,7 @@ import org.mozilla.fenix.utils.Do
* An interface that handles the view manipulation of the BrowserToolbar, triggered by the Interactor * An interface that handles the view manipulation of the BrowserToolbar, triggered by the Interactor
*/ */
interface BrowserToolbarController { interface BrowserToolbarController {
fun handleScroll(offset: Int)
fun handleToolbarPaste(text: String) fun handleToolbarPaste(text: String)
fun handleToolbarPasteAndGo(text: String) fun handleToolbarPasteAndGo(text: String)
fun handleToolbarItemInteraction(item: ToolbarMenu.Item) fun handleToolbarItemInteraction(item: ToolbarMenu.Item)
@ -139,6 +140,10 @@ class DefaultBrowserToolbarController(
} }
} }
override fun handleScroll(offset: Int) {
engineView.setVerticalClipping(offset)
}
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
@SuppressWarnings("ComplexMethod", "LongMethod") @SuppressWarnings("ComplexMethod", "LongMethod")
override fun handleToolbarItemInteraction(item: ToolbarMenu.Item) { override fun handleToolbarItemInteraction(item: ToolbarMenu.Item) {

@ -23,6 +23,7 @@ import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.browser_toolbar_popup_window.view.* import kotlinx.android.synthetic.main.browser_toolbar_popup_window.view.*
import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
import kotlinx.android.synthetic.main.component_browser_top_toolbar.view.* import kotlinx.android.synthetic.main.component_browser_top_toolbar.view.*
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
@ -48,6 +49,7 @@ interface BrowserToolbarViewInteractor {
fun onBrowserToolbarMenuItemTapped(item: ToolbarMenu.Item) fun onBrowserToolbarMenuItemTapped(item: ToolbarMenu.Item)
fun onTabCounterClicked() fun onTabCounterClicked()
fun onBrowserMenuDismissed(lowPrioHighlightItems: List<ToolbarMenu.Item>) fun onBrowserMenuDismissed(lowPrioHighlightItems: List<ToolbarMenu.Item>)
fun onScrolled(offset: Int)
} }
class BrowserToolbarView( class BrowserToolbarView(
@ -140,8 +142,17 @@ class BrowserToolbarView(
with(container.context) { with(container.context) {
val sessionManager = components.core.sessionManager val sessionManager = components.core.sessionManager
if (!shouldUseBottomToolbar) {
val offsetChangedListener =
AppBarLayout.OnOffsetChangedListener { _: AppBarLayout?, verticalOffset: Int ->
interactor.onScrolled(verticalOffset)
}
app_bar.addOnOffsetChangedListener(offsetChangedListener)
}
view.apply { view.apply {
setScrollFlagsForTopToolbar() setScrollFlags()
elevation = TOOLBAR_ELEVATION.dpToFloat(resources.displayMetrics) elevation = TOOLBAR_ELEVATION.dpToFloat(resources.displayMetrics)
@ -241,11 +252,6 @@ class BrowserToolbarView(
} }
} }
@Suppress("UNUSED_PARAMETER")
fun update(state: BrowserFragmentState) {
// Intentionally leaving this as a stub for now since we don't actually want to update currently
}
fun expand() { fun expand() {
if (settings.shouldUseBottomToolbar && FeatureFlags.dynamicBottomToolbar) { if (settings.shouldUseBottomToolbar && FeatureFlags.dynamicBottomToolbar) {
(view.layoutParams as CoordinatorLayout.LayoutParams).apply { (view.layoutParams as CoordinatorLayout.LayoutParams).apply {
@ -256,33 +262,38 @@ class BrowserToolbarView(
} }
} }
companion object { /**
private const val TOOLBAR_ELEVATION = 16 * Dynamically sets scroll flags for the toolbar when the user does not have a screen reader enabled
} * Note that the bottom toolbar has a feature flag for being dynamic, so it may not get flags set.
} */
fun setScrollFlags(shouldDisableScroll: Boolean = false) {
if (view.context.settings().shouldUseBottomToolbar) {
if (FeatureFlags.dynamicBottomToolbar && view.layoutParams is CoordinatorLayout.LayoutParams) {
(view.layoutParams as CoordinatorLayout.LayoutParams).apply {
behavior = BrowserToolbarBottomBehavior(view.context, null)
}
}
return
}
val params = view.layoutParams as AppBarLayout.LayoutParams
/** params.scrollFlags = when (view.context.settings().shouldUseFixedTopToolbar || shouldDisableScroll) {
* Dynamically sets scroll flags for the toolbar when the user does not have a screen reader enabled true -> {
* Note that the bottom toolbar has a feature flag for being dynamic, so it may not get flags set. // Force expand the toolbar so the user is not stuck with a hidden toolbar
*/ expand()
fun BrowserToolbar.setScrollFlagsForTopToolbar() { 0
// Don't set scroll flags for bottom toolbar }
if (context.settings().shouldUseBottomToolbar) { false -> {
if (FeatureFlags.dynamicBottomToolbar && layoutParams is CoordinatorLayout.LayoutParams) { SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS or SCROLL_FLAG_SNAP or SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
(layoutParams as CoordinatorLayout.LayoutParams).apply {
behavior = BrowserToolbarBottomBehavior(context, null)
} }
} }
return view.layoutParams = params
} }
val params = layoutParams as AppBarLayout.LayoutParams companion object {
params.scrollFlags = when (context.settings().shouldUseFixedTopToolbar) { private const val TOOLBAR_ELEVATION = 16
true -> 0
false -> {
SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS or SCROLL_FLAG_SNAP or
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
}
} }
} }

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
package org.mozilla.fenix.components.toolbar
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.appbar.AppBarLayout
import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.engine.EngineView.InputResult.INPUT_RESULT_UNHANDLED
import org.mozilla.fenix.ext.settings
/**
* ScrollingViewBehavior that will setScrollFlags on BrowserToolbar based on EngineView touch handling
*/
class SwipeRefreshScrollingViewBehavior(
context: Context,
attrs: AttributeSet?,
private val engineView: EngineView,
private val browserToolbarView: BrowserToolbarView
) : AppBarLayout.ScrollingViewBehavior(context, attrs) {
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: View,
directTargetChild: View,
target: View,
axes: Int,
type: Int
): Boolean {
if (!browserToolbarView.view.context.settings().shouldUseBottomToolbar) {
val shouldDisable = engineView.getInputResult() == INPUT_RESULT_UNHANDLED
browserToolbarView.setScrollFlags(shouldDisable)
}
return super.onStartNestedScroll(
coordinatorLayout,
child,
directTargetChild,
target,
axes,
type
)
}
}

@ -149,10 +149,6 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
} }
} }
consumeFrom(browserFragmentStore) {
browserToolbarView.update(it)
}
consumeFrom(components.core.customTabsStore) { state -> consumeFrom(components.core.customTabsStore) { state ->
getSessionById() getSessionById()
?.let { session -> session.customTabConfig?.sessionToken } ?.let { session -> session.customTabConfig?.sessionToken }

@ -2,7 +2,8 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this - 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/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<com.google.android.material.appbar.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.appbar.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_bar" android:id="@+id/app_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

@ -2,7 +2,8 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this - 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/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/browserLayout" android:id="@+id/browserLayout"

Loading…
Cancel
Save