
Pylyp Dukhov
Ich verwende BasicTextField.
Wenn ich mit der Bearbeitung beginne, wird die Schaltfläche „Zurück“ zur Schaltfläche „Tastatur ausblenden“ (Pfeil nach unten).
Beim ersten Drücken der Zurück-Taste wird die Tastatur ausgeblendet, aber der Fokus liegt immer noch auf dem Textfeld. Beide onFocusChanged
und BackPressHandler
Handler werden nicht angerufen.
Zweites Drücken der Zurück-Taste löscht den Fokus: onFocusChanged
heißt und BackPressHandler
ist nicht.
BackHandler {
println("BackPressHandler")
}
val valueState = remember { mutableStateOf(TextFieldValue(text = "")) }
BasicTextField(
value = valueState.value,
onValueChange = {
valueState.value = it
},
modifier = Modifier
.fillMaxWidth()
.onFocusChanged {
println("isFocused ${it.isFocused}")
}
)
Beim dritten Mal funktioniert BackHandler einwandfrei. Ich habe es nur zum Testen verwendet, ich sollte es hier nicht brauchen, es wurde erwartet, dass der Fokus nach dem ersten Antippen der Zurück-Taste verloren geht

Pylyp Dukhov
Da ist ein Thema verfassen mit fokussiertem Textfeld verhindert, dass die Zurück-Schaltfläche die App schließt, wenn die Tastatur ausgeblendet ist. Es ist als behoben markiert, wird aber in einer zukünftigen Version enthalten sein, nicht in 1.0
Aber so wie ich es verstehe, ist die Tatsache, dass das Textfeld den Fokus nicht verliert, nachdem die Tastatur geschlossen wurde, ein beabsichtigtes Verhalten auf Android (wegen einer möglichen angeschlossenen Tastatur? Ich habe den Grund nicht verstanden). Und so funktioniert es auch im alten Android-Layout
Es scheint mir seltsam, also kam ich mit dem folgenden Modifikator, der den Fokus aufgibt, wenn die Tastatur verschwindet:
fun Modifier.clearFocusOnKeyboardDismiss(): Modifier = composed {
var isFocused by remember { mutableStateOf(false) }
var keyboardAppearedSinceLastFocused by remember { mutableStateOf(false) }
if (isFocused) {
val imeIsVisible = LocalWindowInsets.current.ime.isVisible
val focusManager = LocalFocusManager.current
LaunchedEffect(imeIsVisible) {
if (imeIsVisible) {
keyboardAppearedSinceLastFocused = true
} else if (keyboardAppearedSinceLastFocused) {
focusManager.clearFocus()
}
}
}
onFocusEvent {
if (isFocused != it.isFocused) {
isFocused = it.isFocused
if (isFocused) {
keyboardAppearedSinceLastFocused = false
}
}
}
}
ps Sie müssen installieren Begleiter-Einsätze Abhängigkeit für LocalWindowInsets.current.ime
Pss Seit Komponieren 1.2.0-alpha03, Begleiter-Einsätze wurde meist eingezogen Stiftung komponierenKasse Migrationsleitfaden für mehr Details. LocalWindowInsets.current.ime
sollte durch ersetzt werden WindowInsets.ime
.
Verwendungszweck:
BasicTextField(
value = valueState.value,
onValueChange = {
valueState.value = it
},
modifier = Modifier
.clearFocusOnKeyboardDismiss()
)
Danke an alle Antworten hier. Nachdem Sie sich auf die Antworten hier bezogen haben, finden Sie hier eine Lösung ohne Verwendung einer Bibliothek
1. Erstellen Sie eine Erweiterung in View, um festzustellen, ob die Tastatur geöffnet ist oder nicht
fun View.isKeyboardOpen(): Boolean {
val rect = Rect()
getWindowVisibleDisplayFrame(rect);
val screenHeight = rootView.height
val keypadHeight = screenHeight - rect.bottom;
return keypadHeight > screenHeight * 0.15
}
2. Erstellen Sie einen beobachtbaren Zustand, um festzustellen, ob eine Tastatur geöffnet ist oder nicht
Dadurch werden globale Layout-Updates auf LocalView überwacht, bei denen wir bei jedem Ereignis den Status zum Öffnen/Schließen der Tastatur prüfen.
@Composable
fun rememberIsKeyboardOpen(): State<Boolean> {
val view = LocalView.current
return produceState(initialValue = view.isKeyboardOpen()) {
val viewTreeObserver = view.viewTreeObserver
val listener = OnGlobalLayoutListener { value = view.isKeyboardOpen() }
viewTreeObserver.addOnGlobalLayoutListener(listener)
awaitDispose { viewTreeObserver.removeOnGlobalLayoutListener(listener) }
}
}
3. Modifikator erstellen
Dieser Modifikator sorgt dafür, dass der Fokus auf sichtbare/unsichtbare Tastaturereignisse gelöscht wird.
fun Modifier.clearFocusOnKeyboardDismiss(): Modifier = composed {
var isFocused by remember { mutableStateOf(false) }
var keyboardAppearedSinceLastFocused by remember { mutableStateOf(false) }
if (isFocused) {
val isKeyboardOpen by rememberIsKeyboardOpen()
val focusManager = LocalFocusManager.current
LaunchedEffect(isKeyboardOpen) {
if (isKeyboardOpen) {
keyboardAppearedSinceLastFocused = true
} else if (keyboardAppearedSinceLastFocused) {
focusManager.clearFocus()
}
}
}
onFocusEvent {
if (isFocused != it.isFocused) {
isFocused = it.isFocused
if (isFocused) {
keyboardAppearedSinceLastFocused = false
}
}
}
}
4. Verwenden Sie es
Verwenden Sie es schließlich mit TextField
zusammensetzbar
BasicTextField(Modifier.clearFocusOnKeyboardDismiss())

mmm111mm
Ich habe eine wohl einfachere Lösung mit dem Baumbeobachter von Android gefunden.
Sie müssen keine andere Bibliothek verwenden oder die Einsätze aus Ihrem Layout entfernen.
Es löscht den Fokus beim Verfassen jedes Mal, wenn die Tastatur ausgeblendet ist.
Hoffentlich wird dies wann nicht mehr nötig sein diese es ist veröffentlicht worden.
class MainActivity : ComponentActivity() {
var kbClosed: () -> Unit = {}
var kbClosed: Boolean = false
override fun onCreate(state: Bundle?) {
super.onCreate(state)
setContent {
val focusManager = LocalFocusManager.current
kbClosed = {
focusManager.clearFocus()
}
MyComponent()
}
setupKeyboardDetection(findViewById<View>(android.R.id.content))
}
fun setupKeyboardDetection(contentView: View) {
contentView.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
contentView.getWindowVisibleDisplayFrame(r)
val screenHeight = contentView.rootView.height
val keypadHeight = screenHeight - r.bottom
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
kbClosed = false
// kb opened
} else if(!kbClosed) {
kbClosed = true
kbClosed()
}
}
}
}
Fügen Sie in einer Klasse, die von Application erbt, den folgenden Code hinzu, um zu erkennen, wann die Hauptaktivität erstellt wird, und fügen Sie den Code hinzu, der erkennt, wann die Tastatur angezeigt oder ausgeblendet wird:
import android.app.Activity
import android.app.Application
import android.content.res.Resources
import android.graphics.Rect
import android.os.Bundle
import android.util.DisplayMetrics
import androidx.compose.runtime.mutableStateOf
class App : Application() {
private val activityLifecycleTracker: AppLifecycleTracker = AppLifecycleTracker()
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(activityLifecycleTracker)
}
companion object {
val onKeyboardClosed = mutableStateOf(false)
}
/**
* Callbacks for handling the lifecycle of activities.
*/
class AppLifecycleTracker : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, p1: Bundle?) {
val displayMetrics: DisplayMetrics by lazy { Resources.getSystem().displayMetrics }
val screenRectPx = displayMetrics.run { Rect(0, 0, widthPixels, heightPixels) }
// Detect when the keyboard closes.
activity.window.decorView.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
activity.window.decorView.getWindowVisibleDisplayFrame(r)
val heightDiff: Int = screenRectPx.height() - (r.bottom - r.top)
onKeyboardClosed.value = (heightDiff <= 100)
}
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(p0: Activity) {
}
override fun onActivityStopped(activity: Activity) {
}
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {
}
override fun onActivityDestroyed(p0: Activity) {
}
}
}
Fügen Sie die folgende Modifikatorerweiterung hinzu:
@Stable
fun Modifier.clearFocusOnKeyboardClose(focusManager: FocusManager): Modifier {
if (App.onKeyboardClosed.value) {
focusManager.clearFocus()
}
return this
}
Fügen Sie in Ihrem Composable einen Verweis auf den FocusManager hinzu und fügen Sie den Modifikator zu Ihrem TextField hinzu:
@Composable
fun MyComposable() {
val focusManager = LocalFocusManager.current
OutlinedTextField(
modifier = Modifier.clearFocusOnKeyboardClose(focusManager = focusManager)
)
}
Das TextField löscht seinen Fokus, wenn die Tastatur geschlossen wird.
10141200cookie-checkWie lösche ich den TextField-Fokus beim Schließen der Tastatur und verhindere, dass zwei Rückdrücke erforderlich sind, um die App in Jetpack Compose zu beenden?yes
Laut den Release Notes ist dies in 1.1.0 behoben jetc.dev/issues/077.html
– mmm111mm
24. August 2021 um 6:01 Uhr
@mmm111mmm aus dem Gespräch rein Thema verfassen Ich verstehe, dass nach dem Fix Second Back die App geschlossen wird, aber das Schließen der Tastatur wird den Fokus immer noch nicht löschen, was immer noch nicht das ist, was ich in meiner App erwarte
– Pylyp Dukhov
24. August 2021 um 6:05 Uhr