Status Update
Comments
ke...@fbinv.com <ke...@fbinv.com> #2
Branch: androidx-master-dev
commit c60f33e229e31ab328ef6b59dab63b264954831c
Author: Alexandre Elias <aelias@google.com>
Date: Fri Jul 10 16:23:09 2020
Semantics no-op cleanups
Partly in response to lmr's broad code review, I did a pass of
superficial API/implementation cleanup. The main changes are:
- I changed each Boolean SemanticsProperty where false is equivalent to
not being present to take "Unit" instead. This is conceptually
clearer: it avoids questions like "can I cancel out a semantics from a
merged child by setting it to false?" Because "property = Unit" looks
weird, I also changed the style of these to "property()".
- I moved the Semantics id generator closer to where it's used, in
SemanticsModifierCore. I made it internal and an AtomicInt.
(Note that integer ids are heavily used in the Android
AccessibilityNodeInfo APIs so I can't simply remove them entirely.)
- I deleted dead code. Some examples include SemanticsHintOverrides,
a public API not connected to anything, and SemanticsPropertyKey
merge() open method which is never called. (In both cases I have
a different plan in mind for accessibility.)
Fixes: 145951226
Fixes: 145955412
Test: existing tests
Relnote: "Single-value semantics properties now use a calling style.
For example, 'semantics { hidden = true }' is now written as:
'semantics { hidden() }'."
Change-Id: Ic1afd12ea22c926babc9662f1804d80b33aa0cfc
M ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
M ui/ui-core/api/0.1.0-dev15.txt
M ui/ui-core/api/current.txt
M ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-core/api/public_plus_experimental_current.txt
M ui/ui-core/api/restricted_0.1.0-dev15.txt
M ui/ui-core/api/restricted_current.txt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/VectorTest.kt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/semantics/SemanticsTests.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidActuals.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidPopup.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/Expect.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsConfiguration.kt
D ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsHintOverrides.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsOwner.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/semantics/SemanticsProperties.kt
M ui/ui-foundation/api/0.1.0-dev15.txt
M ui/ui-foundation/api/current.txt
M ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-foundation/api/public_plus_experimental_current.txt
M ui/ui-foundation/api/restricted_0.1.0-dev15.txt
M ui/ui-foundation/api/restricted_current.txt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Dialog.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/semantics/FoundationSemanticsProperties.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CardTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SurfaceTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
M ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
M ui/ui-material/src/main/java/androidx/ui/material/TextFieldImpl.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/AssertsTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/CallSemanticsActionTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ErrorMessagesTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/PrintToStringTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/TextActionsTest.kt
M ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
M ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
M ui/ui-text/api/0.1.0-dev15.txt
M ui/ui-text/api/current.txt
M ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-text/api/public_plus_experimental_current.txt
M ui/ui-text/api/restricted_0.1.0-dev15.txt
M ui/ui-text/api/restricted_current.txt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/CoreTextField.kt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/TextSemanticsProperties.kt
ro...@gmail.com <ro...@gmail.com> #3
Same here. I need to do a custom action when pressing back when the modal is open. This is related to
ke...@google.com <ke...@google.com>
ke...@google.com <ke...@google.com>
ke...@google.com <ke...@google.com>
ap...@google.com <ap...@google.com> #4
Branch: androidx-main
commit 90075b00a1b5e5ebd24fb8c03f8a3fc2a7c72e98
Author: Kevin Truong <kevinctruong@google.com>
Date: Wed Oct 04 16:06:44 2023
[BottomSheet] Adding ModalBottomSheetProperties class
Adding a ModalBottomSheetProperties that contains securePolicy, isFocuable, and shouldDismissOnBackPress. securePolicy is taken from the ModalBottomSheet API and placed into this class for neatness.
isFocusable and shouldDismissOnBackPress are parameters that can be used to determine if the modal bottom sheet should receive IME events, and shouldDismissOnBackPress determines if the modal bottom sheet should dismiss when back is pressed on the IME. These parameters are ported from PopupProperties and the implementation is very similar to their usage within Popup.
Bug: 278216859
Test: Updating modalBottomSheet_imePadding test to use the isFocusable parameter, so the text field within the modal bottom sheet can receive focus.
Relnote: adding ModalBottomSheetProperties. Moving securePolicy into ModalBottomSheetProperties. Adding isFocusable and shouldDismissOnBackPress to ModalBottomSheetProperties. These new booleans help determine how modal bottom sheet should handle IME events.
Change-Id: Iea56ff84fd2f8a70037607e8aef0ceaf7a47e3d0
M compose/material3/material3/api/current.txt
M compose/material3/material3/api/restricted_current.txt
M compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
M compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
ru...@gmail.com <ru...@gmail.com> #5
Any chance for a release including this fix soon?
ke...@payback.net <ke...@payback.net> #6
tf...@gmail.com <tf...@gmail.com> #7
There’s already a dedicated issue about the back not working when android:enableOnBackInvokedCallback=“true”
is set:
It seems like it’s blocked by a general lack of predictive back support in Compose, though:
sh...@navi.com <sh...@navi.com> #8
ar...@gmail.com <ar...@gmail.com> #9
I've tried androidx.compose.material3:material3:1.2.0-beta01
and I believe it's still not working. BackHandler {}
is not called inside ModalBottomSheet
, the sheet is closing instead.
ay...@gmail.com <ay...@gmail.com> #10
Any ideas on why this is marked as fixed?
el...@ur.se <el...@ur.se> #11
tf...@gmail.com <tf...@gmail.com> #12
The fix wasn't to support BackHandler {}
. They just added a new properties
arg that you can set whether the sheet should be dismissed on back or not:
ModalBottomSheet(
...
properties = ModalBottomSheetDefaults.properties(shouldDismissOnBackPress = /* boolean goes here */),
...
)
Since the sheet is in a separate window, I'm afraid this might be the best they can do. That's pretty similar to the API of dialogs, which also have their own window:
Dialog(
...
properties = DialogProperties(dismissOnBackPress = /* boolean goes here */),
...
)
But of course the APIs aren't super consistent 😅
as...@gmail.com <as...@gmail.com> #13
da...@tixr.com <da...@tixr.com> #14
The bug as it's stated in the title and the snippet still exists despite the "fix": it remains impossible to use a BackHandler
inside a ModalBottomSheet.
Some thoughts after looking at the code: somehow the ModalBottomSheetWindow
needs to implement a OnBackPressedDispatcherOwner
and delegate to it when back is pressed (in dispatchKeyEvent
), instead of directly calling onDismissRequest like it does today (material3 version 1.2.0).
I note that the "ModalBottomSheetWindow" is actually a View
, not a Window
-- perhaps that's why this is not trivial to fix.
Knowing the code doesn't give me a good idea for a workaround though...
da...@tixr.com <da...@tixr.com> #15
I have found a workaround. It consists in intercepting the key event, doing the same checks that ModalBottomSheetWindow.dispatchKeyEvent
would do, and then delegating that to the OnBackPressedDispatcherOwner
manually.
@Composable
fun ModalBottomSheetWithBackHandling(
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
sheetState: SheetState = rememberModalBottomSheetState(),
properties: ModalBottomSheetProperties = ModalBottomSheetDefaults.properties(),
content: @Composable ColumnScope.() -> Unit,
) {
val scope = rememberCoroutineScope()
BackHandler(enabled = sheetState.targetValue != SheetValue.Hidden) {
// Always catch back here, but only let it dismiss if shouldDismissOnBackPress.
// If not, it will have no effect.
if (properties.shouldDismissOnBackPress) {
scope.launch { sheetState.hide() }.invokeOnCompletion {
if (!sheetState.isVisible) {
onDismissRequest()
}
}
}
}
val requester = remember { FocusRequester() }
val backPressedDispatcherOwner = LocalOnBackPressedDispatcherOwner.current
ModalBottomSheet(
onDismissRequest = onDismissRequest,
modifier = modifier
.focusRequester(requester)
.focusable()
.onPreviewKeyEvent {
if (it.key == Key.Back && it.type == KeyEventType.KeyUp && !it.nativeKeyEvent.isCanceled) {
backPressedDispatcherOwner?.onBackPressedDispatcher?.onBackPressed()
return@onPreviewKeyEvent true
}
return@onPreviewKeyEvent false
},
properties = ModalBottomSheetDefaults.properties(
securePolicy = properties.securePolicy,
isFocusable = properties.isFocusable,
// Set false otherwise the onPreviewKeyEvent doesn't work at all.
// The functionality of shouldDismissOnBackPress is achieved by the BackHandler.
shouldDismissOnBackPress = false,
),
content = content,
)
LaunchedEffect(Unit) {
requester.requestFocus()
}
}
ni...@gmail.com <ni...@gmail.com> #16
Thank you for your workaround code!
j6...@gmail.com <j6...@gmail.com> #17
The problem is if you're using focusManager.clearFocus()
anywhere in your code the ModalBottomSheet will lose focus.
da...@tixr.com <da...@tixr.com> #18
BackHandler seems to be working in androidx.compose.material3:material3:1.3.0-beta02 out of the box without the workaround I posted a couple of messages above.
de...@gmail.com <de...@gmail.com> #19
pb...@gmail.com <pb...@gmail.com> #20
jo...@gmail.com <jo...@gmail.com> #21
se...@gmail.com <se...@gmail.com> #22
The short version of this solution that worked for me:
Description
Given the code
Steps:
Expectation: BackHandler's lambda is called and snackbar appears on the screen.
Reality: modal bottom sheet closes.