Jetpack Compose 在 Wear OS 上 BasicTextField 的问题

4
我刚开始使用Compose,我在Wear OS上遇到了输入文本字段的问题。问题是我无法像在Android上一样使用软键盘。当我尝试在XML中实现相同的布局时,它却可以工作。 因此,当我点击输入文本字段时,键盘弹出然后隐藏。再次点击时,键盘弹出并保持打开状态,但如果我尝试输入任何内容,则输入字段中没有任何内容显示(在键盘本身上),尽管已输入的文本传递到了UI上的输入文本字段中。
以下是我在模拟器日志中点击输入文本字段以打开键盘时获得的内容:
2021-11-24 09:44:36.569 W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection
2021-11-24 09:44:36.571 W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection
2021-11-24 09:44:36.649 W/RecordingIC: requestCursorUpdates is not supported

这是我在真实设备上获得的结果:

2021-11-24 09:35:39.783 W/IInputConnectionWrapper: getExtractedText on inactive InputConnection
2021-11-24 09:35:39.872 W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: setComposingRegion on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection
2021-11-24 09:35:39.873 W/IInputConnectionWrapper: getExtractedText on inactive InputConnection
2021-11-24 09:35:39.882 W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection
2021-11-24 09:35:39.883 W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection
2021-11-24 09:35:39.884 W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection
2021-11-24 09:35:39.888 W/IInputConnectionWrapper: getSelectedText on inactive InputConnection
2021-11-24 09:35:39.890 W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection
2021-11-24 09:35:39.891 W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection
2021-11-24 09:35:39.891 W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection
2021-11-24 09:35:39.891 W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection
2021-11-24 09:35:39.891 W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection

这是我的“可组合”代码:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun ActivationScreen() {

    var key by remember { mutableStateOf("") }

    var isReady by remember {
        mutableStateOf(false)
    }

    Column(modifier = Modifier
        .padding(40.dp)
        .fillMaxSize()
    ) {
        val keyboardController = LocalSoftwareKeyboardController.current
        val focusRequester = FocusRequester()
        BasicTextField(
            value = key,
            onValueChange = {
                //isReady = it.length>11
                key = it
            },
            singleLine = true,
            keyboardOptions = KeyboardOptions.Default.copy(
                imeAction = ImeAction.Done
            ),
            keyboardActions = KeyboardActions(
                onDone = {
                    keyboardController?.hide()
                }
            ),
            modifier = Modifier
                .size(140.dp, 20.dp)
                .background(Color.White)
                .align(Alignment.CenterHorizontally)
                //.focusRequester(focusRequester)
                //.focusOrder(focusRequester)
        )

        Text(
            text = "ACTIVATION",
        )

        val status = if (isReady) "READY" else "NOT READY"
        Text(
            text = status,
        )
    }
}

1
可穿戴设备上的文本输入并不是Compose for WearOS中优先考虑的内容,但预计最终会实现。其他人也报告了可重现的问题。在此处提出错误报告:https://issuetracker.google.com/issues?q=componentid:1077552%20status:open - Yuri Schimke
我有类似的问题。你解决了这个问题吗? - AlexandraFilyakova
2个回答

10

在 Wear 上应该避免文字输入,但如果确实需要,可以使用 GBoard activity 来激活。

请参见 https://developer.android.com/reference/androidx/wear/input/RemoteInputIntentHelper.Companion#createActionRemoteInputIntent()

@Composable
fun TextInput() {
  val label = remember { mutableStateOf("Start")}
  val launcher =
    rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
      it.data?.let { data ->
        val results: Bundle = RemoteInput.getResultsFromIntent(data)
        val ipAddress: CharSequence? = results.getCharSequence("ip_address")
        label.value = ipAddress as String
      }
    }
  Column() {
    Spacer(modifier = Modifier.height(20.dp))
    Chip(
      label = { Text(label.value) },
      onClick = {}
    )
    Chip(
      label = { Text("Search with specific IP") },
      onClick = {
        val intent: Intent = RemoteInputIntentHelper.createActionRemoteInputIntent();
        val remoteInputs: List<RemoteInput> = listOf(
          RemoteInput.Builder("ip_address")
            .setLabel("Manual IP Entry")
            .wearableExtender {
              setEmojisAllowed(false)
              setInputActionType(EditorInfo.IME_ACTION_DONE)
            }.build()
        )

        RemoteInputIntentHelper.putRemoteInputsExtra(intent, remoteInputs)

        launcher.launch(intent)
      }
    )
  }
}

注意:正如@TiagoPeresFrança在评论中提到的:
要使用wearableExtender,您必须使用wear-input依赖的1.2.0+版本。截至今天,应该使用1.2.0-alpha02版本。在您的应用gradle文件中,请确保您具有以下依赖项:implementation 'androidx.wear:wear-input:1.2.0-alpha02'

Yuri,很抱歉,我别无选择——该应用程序在独立模式下工作,需要非常基本的文本输入。你的方法正是我正在寻找的。谢谢! - Dmitry
@Dmitry 你需要导入或安装其他库吗?我无法导入RemoteInputIntentHelper。 - Francisco Hanna
@FranciscoHanna 我已经导入了androidx.wear.input.RemoteInputIntentHelper。 - Dmitry
1
为了让wearableExtender正常工作,您必须使用wear-input依赖的1.2.0+版本。截至今天,应该使用1.2.0-alpha02版本。在您的应用gradle文件中,请确保您有以下依赖:implementation 'androidx.wear:wear-input:1.2.0-alpha02' - Tiago Peres França
3
你从哪里得到了可穿戴扩展器? - Jéwôm'
可以同时禁用语音功能并直接打开键盘吗? - muellerelias

0

基于@Yuri Schimke的答案,这里提供了一个通用组件实现,可以接受占位符、值和onChange作为属性。

import android.app.RemoteInput
import android.content.Intent
import android.os.Bundle
import android.view.inputmethod.EditorInfo
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.Text
import androidx.wear.input.RemoteInputIntentHelper
import androidx.wear.input.wearableExtender

@Composable
fun TextInput(
  placeholder: String,
  value: String?,
  onChange: (value: String) -> Unit,
) {
  val launcher =
    rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
      it.data?.let { data ->
        val results: Bundle = RemoteInput.getResultsFromIntent(data)
        val newValue: CharSequence? = results.getCharSequence(placeholder)
        onChange(newValue as String)
      }
    }
  Column() {
    Chip(
      label = { Text(if (value == null || value.isEmpty()) placeholder else value) },
      onClick = {
        val intent: Intent = RemoteInputIntentHelper.createActionRemoteInputIntent();
        val remoteInputs: List<RemoteInput> = listOf(
          RemoteInput.Builder(placeholder)
            .setLabel(placeholder)
            .wearableExtender {
              setEmojisAllowed(false)
              setInputActionType(EditorInfo.IME_ACTION_DONE)
            }.build()
        )

        RemoteInputIntentHelper.putRemoteInputsExtra(intent, remoteInputs)

        launcher.launch(intent)
      }
    )
  }
}

注意:这需要androidx.wear:wear-input:1.2.0+。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接