For #26957 - Allow SearchDialogFragment to be dismissed on homescreen swipe

This commit is contained in:
Alexandru2909 2022-12-16 17:49:24 +02:00 committed by mergify[bot]
parent d07de1e028
commit 782a903072
3 changed files with 29 additions and 59 deletions

View File

@ -1,57 +0,0 @@
/* 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.home
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.MotionEvent.ACTION_UP
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.navigation.findNavController
import mozilla.components.support.ktx.android.view.findViewInHierarchy
import org.mozilla.fenix.R
import org.mozilla.fenix.search.SearchDialogFragment
/**
* Parent layout for [HomeFragment], used to dismiss the [SearchDialogFragment] when
* interacting with elements in the [HomeFragment].
*/
class HomeFragmentLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : CoordinatorLayout(context, attrs, defStyleAttr) {
/**
* Returns whether or not the motion event is touching the private browsing button.
*
* @param x X coordinate of the event.
* @param y Y coordinate of the event.
*/
private fun isTouchingPrivateButton(x: Float, y: Float): Boolean {
val view = this.findViewInHierarchy {
it.id == R.id.privateBrowsingButton
} ?: return false
val privateButtonRect = Rect()
view.getHitRect(privateButtonRect)
return privateButtonRect.contains(x.toInt(), y.toInt())
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
val nav = findNavController()
// If the private button is touched from the [SearchDialogFragment], then it should not be
// dismissed to allow the user to continue the search.
if (ev?.action == ACTION_UP &&
nav.currentDestination?.id == R.id.searchDialogFragment &&
!isTouchingPrivateButton(ev.x, ev.y)
) {
nav.popBackStack()
}
return super.onInterceptTouchEvent(ev)
}
}

View File

@ -20,6 +20,7 @@ import android.os.Bundle
import android.speech.RecognizerIntent
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
@ -67,6 +68,7 @@ import mozilla.components.support.ktx.android.content.hasCamera
import mozilla.components.support.ktx.android.content.isPermissionGranted
import mozilla.components.support.ktx.android.content.res.getSpanned
import mozilla.components.support.ktx.android.net.isHttpOrHttps
import mozilla.components.support.ktx.android.view.findViewInHierarchy
import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.kotlin.toNormalizedUrl
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
@ -83,6 +85,7 @@ import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.databinding.FragmentSearchDialogBinding
import org.mozilla.fenix.databinding.SearchSuggestionsHintBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getRectWithScreenLocation
import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings
@ -118,6 +121,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
private val qrFeature = ViewBoundFeatureWrapper<QrFeature>()
private val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
private var isPrivateButtonClicked = false
private var dialogHandledAction = false
private var searchSelectorAlreadyAdded = false
private var qrButtonAction: Toolbar.Action? = null
@ -267,6 +271,22 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
// When displayed above home, dispatches the touch events to scrim area to the HomeFragment
binding.searchWrapper.background = ColorDrawable(Color.TRANSPARENT)
dialog?.window?.decorView?.setOnTouchListener { _, event ->
when (event?.action) {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
isPrivateButtonClicked = isTouchingPrivateButton(event.x, event.y)
}
MotionEvent.ACTION_UP -> {
if (!isTouchingPrivateButton(
event.x,
event.y,
) && !isPrivateButtonClicked
) {
findNavController().popBackStack()
isPrivateButtonClicked = false
}
}
else -> isPrivateButtonClicked = false
}
requireActivity().dispatchTouchEvent(event)
false
}
@ -457,6 +477,13 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler {
}
}
private fun isTouchingPrivateButton(x: Float, y: Float): Boolean {
val view = parentFragmentManager.primaryNavigationFragment?.view?.findViewInHierarchy {
it.id == R.id.privateBrowsingButton
} ?: return false
return view.getRectWithScreenLocation().contains(x.toInt(), y.toInt())
}
private fun hideClipboardSection() {
binding.fillLinkFromClipboard.isVisible = false
binding.fillLinkDivider.isVisible = false

View File

@ -6,7 +6,7 @@
<!-- using an AppBarLayout to replace MotionLayout was done in order to improve Fenix
start up performance. The use of a MotionLayout was worsening our layout measures, especially
with the recycler view -->
<org.mozilla.fenix.home.HomeFragmentLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@ -202,4 +202,4 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</org.mozilla.fenix.home.HomeFragmentLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>