diff --git a/FluentUI.Demo/src/main/AndroidManifest.xml b/FluentUI.Demo/src/main/AndroidManifest.xml index d937e187a..49a6cf3aa 100644 --- a/FluentUI.Demo/src/main/AndroidManifest.xml +++ b/FluentUI.Demo/src/main/AndroidManifest.xml @@ -35,8 +35,7 @@ + android:windowSoftInputMode="adjustResize"/> diff --git a/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2BottomDrawerActivity.kt b/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2BottomDrawerActivity.kt index c4b45f361..59a06b257 100644 --- a/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2BottomDrawerActivity.kt +++ b/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2BottomDrawerActivity.kt @@ -5,8 +5,6 @@ import SearchViewModelFactory import Searchable import android.content.res.Configuration import android.os.Bundle -import androidx.activity.OnBackPressedCallback -import androidx.activity.compose.LocalOnBackPressedDispatcherOwner import androidx.compose.animation.core.animateDpAsState import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.Orientation @@ -92,22 +90,11 @@ class V2BottomDrawerActivity : V2DemoActivity() { override val paramsUrl = "https://github.com/microsoft/fluentui-android/wiki/Controls#params-9" override val controlTokensUrl = "https://github.com/microsoft/fluentui-android/wiki/Controls#control-tokens-9" - private val onBackCallback = - object : OnBackPressedCallback(true) { //callback to end the activity - override fun handleOnBackPressed() { - finish() - } - - } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setActivityContent { CreateActivityUI() - LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher?.addCallback( - this, - onBackCallback - ) //registering the callback to end the activity when back button is pressed } } } @@ -566,7 +553,7 @@ private fun CreateSearchableDrawerWithButtonOnPrimarySurfaceToInvokeIt( ) val open: () -> Unit = { scope.launch { - if(drawerState.currentValue == DrawerValue.Closed) { + if (drawerState.currentValue == DrawerValue.Closed) { viewModel.clearSelection() } drawerState.open() diff --git a/azure-maven-central-pipelines.yml b/azure-maven-central-pipelines.yml index eeedefcb6..3ca5ba3f6 100644 --- a/azure-maven-central-pipelines.yml +++ b/azure-maven-central-pipelines.yml @@ -50,6 +50,7 @@ jobs: - task: Gradle@2 displayName: Hydra Lab UI test + condition: eq(coalesce(variables['runHydraLabTests'], 'false'), 'true') inputs: gradleWrapperFile: "gradlew" tasks: "requestHydraLabTest -PappPath=$(build.sourcesdirectory)/FluentUI.Demo/build/outputs/apk/development/debug/FluentUI.Demo-development-debug.apk -PtestAppPath=$(build.sourcesdirectory)/FluentUI.Demo/build/outputs/apk/androidTest/development/debug/FluentUI.Demo-development-debug-androidTest.apk -PbuildFlavor=$(buildFlavor) -PtestSuiteName=$(testSuiteName) -PrunTimeOutSeconds=$(timeOutSeconds) -PdeviceIdentifier=$(deviceIdentifier) -PgroupTestType=$(groupTestType) -PreportAudience=TestLabOwner -PauthToken=$(authToken) -PpkgName=$(pkgName) -PtestPkgName=$(testPkgName) -PrunningType=$(runningType) -PframeworkType=$(frameworkType) -PhydraLabAPIHost=$(hydraLabAPIHost) -PhydraLabAPISchema=$(hydraLabAPISchema)" diff --git a/azure-pipelines-fork-build-push.yml b/azure-pipelines-fork-build-push.yml index 953cecf8e..a3b5e7d2f 100644 --- a/azure-pipelines-fork-build-push.yml +++ b/azure-pipelines-fork-build-push.yml @@ -56,6 +56,7 @@ jobs: - task: Gradle@3 displayName: Hydra Lab UI test + condition: eq(coalesce(variables['runHydraLabTests'], 'false'), 'true') inputs: gradleWrapperFile: "gradlew" tasks: "requestHydraLabTest -PappPath=$(build.sourcesdirectory)/FluentUI.Demo/build/outputs/apk/development/debug/FluentUI.Demo-development-debug.apk -PtestAppPath=$(build.sourcesdirectory)/FluentUI.Demo/build/outputs/apk/androidTest/development/debug/FluentUI.Demo-development-debug-androidTest.apk -PbuildFlavor=$(buildFlavor) -PtestSuiteName=$(testSuiteName) -PrunTimeOutSeconds=$(timeOutSeconds) -PdeviceIdentifier=$(deviceIdentifier) -PgroupTestType=$(groupTestType) -PreportAudience=TestLabOwner -PauthToken=$(authToken) -PpkgName=$(pkgName) -PtestPkgName=$(testPkgName) -PrunningType=$(runningType) -PframeworkType=$(frameworkType) -PhydraLabAPIHost=$(hydraLabAPIHost) -PhydraLabAPISchema=$(hydraLabAPISchema)" diff --git a/fluentui-maven-central-publish-1espt.yml b/fluentui-maven-central-publish-1espt.yml index fd4c5681f..f8a62286b 100644 --- a/fluentui-maven-central-publish-1espt.yml +++ b/fluentui-maven-central-publish-1espt.yml @@ -62,6 +62,7 @@ extends: spotBugsAnalysis: false - task: Gradle@2 displayName: Hydra Lab UI test + condition: eq(coalesce(variables['runHydraLabTests'], 'false'), 'true') inputs: gradleWrapperFile: "gradlew" tasks: "requestHydraLabTest -PappPath=$(build.sourcesdirectory)/FluentUI.Demo/build/outputs/apk/development/debug/FluentUI.Demo-development-debug.apk -PtestAppPath=$(build.sourcesdirectory)/FluentUI.Demo/build/outputs/apk/androidTest/development/debug/FluentUI.Demo-development-debug-androidTest.apk -PbuildFlavor=$(buildFlavor) -PtestSuiteName=$(testSuiteName) -PrunTimeOutSeconds=$(timeOutSeconds) -PdeviceIdentifier=$(deviceIdentifier) -PgroupTestType=$(groupTestType) -PreportAudience=TestLabOwner -PauthToken=$(authToken) -PpkgName=$(pkgName) -PtestPkgName=$(testPkgName) -PrunningType=$(runningType) -PframeworkType=$(frameworkType) -PhydraLabAPIHost=$(hydraLabAPIHost) -PhydraLabAPISchema=$(hydraLabAPISchema)" diff --git a/fluentui_core/src/main/java/com/microsoft/fluentui/compose/ModalPopup.kt b/fluentui_core/src/main/java/com/microsoft/fluentui/compose/ModalPopup.kt index 600618998..2102c2b18 100644 --- a/fluentui_core/src/main/java/com/microsoft/fluentui/compose/ModalPopup.kt +++ b/fluentui_core/src/main/java/com/microsoft/fluentui/compose/ModalPopup.kt @@ -6,6 +6,7 @@ import android.graphics.PixelFormat import android.graphics.Rect import android.os.Build import android.view.Gravity +import android.view.KeyEvent import android.view.View import android.view.ViewGroup import android.view.ViewOutlineProvider @@ -66,13 +67,15 @@ import java.util.UUID */ @Composable fun ModalPopup( - onDismissRequest:(() -> Unit)? = null, + onDismissRequest: (() -> Unit)? = null, + properties: PopupProperties = PopupProperties( + focusable = true, + dismissOnBackPress = true, + dismissOnClickOutside = true + ), windowInsetsType: Int = WindowInsetsCompat.Type.systemBars(), content: @Composable () -> Unit, ) { - val properties = PopupProperties( - focusable = true, - ) val view = LocalView.current val density = LocalDensity.current val layoutDirection = LocalLayoutDirection.current @@ -263,6 +266,25 @@ private class ModalWindow( // Do nothing. } + override fun dispatchKeyEvent(event: KeyEvent): Boolean { + if (event.keyCode == KeyEvent.KEYCODE_BACK && properties.dismissOnBackPress) { + if (keyDispatcherState == null) { + return super.dispatchKeyEvent(event) + } + val state = keyDispatcherState + if (event.action == KeyEvent.ACTION_DOWN && event.repeatCount == 0) { + state?.startTracking(event, this) + return true + } else if (event.action == KeyEvent.ACTION_UP) { + if (state != null && state.isTracking(event) && !event.isCanceled) { + onDismissRequest?.invoke() + return true + } + } + } + return super.dispatchKeyEvent(event) + } + fun superSetLayoutDirection(layoutDirection: LayoutDirection) { val direction = when (layoutDirection) { LayoutDirection.Ltr -> android.util.LayoutDirection.LTR @@ -271,7 +293,7 @@ private class ModalWindow( super.setLayoutDirection(direction) } - private fun createLayoutParams(): WindowManager.LayoutParams{ + private fun createLayoutParams(): WindowManager.LayoutParams { return WindowManager.LayoutParams().apply { // Position bottom sheet from the bottom of the screen gravity = Gravity.BOTTOM or Gravity.START @@ -326,7 +348,11 @@ private open class PopupLayoutHelperImpl { @RequiresApi(29) // android.view.View#setSystemGestureExclusionRects call requires API 29 and above private class PopupLayoutHelperImpl29 : PopupLayoutHelperImpl() { - override fun setGestureExclusionRects(composeView: View, width: Int, height: Int) { // We need to explicitly specify to exclude the entire screen from system gestures + override fun setGestureExclusionRects( + composeView: View, + width: Int, + height: Int + ) { // We need to explicitly specify to exclude the entire screen from system gestures composeView.systemGestureExclusionRects = mutableListOf( Rect( 0, diff --git a/fluentui_drawer/src/main/java/com/microsoft/fluentui/tokenized/drawer/Drawer.kt b/fluentui_drawer/src/main/java/com/microsoft/fluentui/tokenized/drawer/Drawer.kt index c5e1be86a..0ab6bde20 100644 --- a/fluentui_drawer/src/main/java/com/microsoft/fluentui/tokenized/drawer/Drawer.kt +++ b/fluentui_drawer/src/main/java/com/microsoft/fluentui/tokenized/drawer/Drawer.kt @@ -1,6 +1,5 @@ package com.microsoft.fluentui.tokenized.drawer -import androidx.activity.compose.BackHandler import androidx.compose.foundation.Canvas import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.fillMaxSize @@ -327,7 +326,10 @@ internal fun Scrim( } @Composable -internal fun AnnounceDrawerActions(drawerState: DrawerState, talkbackAnnouncement: DrawerAccessibilityAnnouncement){ // Announces actions for drawer through Talkback +internal fun AnnounceDrawerActions( + drawerState: DrawerState, + talkbackAnnouncement: DrawerAccessibilityAnnouncement +) { // Announces actions for drawer through Talkback val view = LocalView.current var previousState by remember { mutableStateOf(drawerState.enable) } @@ -343,6 +345,7 @@ internal fun AnnounceDrawerActions(drawerState: DrawerState, talkbackAnnouncemen } } + /** * * Drawer block interaction with the rest of an app’s content with a scrim. @@ -522,12 +525,16 @@ fun BottomDrawer( scope.launch { drawerState.close() } } } - BackHandler { //TODO: Add pull down animation with predictive back - close() - } ModalPopup( windowInsetsType = windowInsetsType, - onDismissRequest = close, + properties = PopupProperties( + focusable = true, + dismissOnBackPress = true, + dismissOnClickOutside = false + ), + onDismissRequest = { + close() + }, ) { val drawerShape: Shape =