简体   繁体   English

Jetpack Compose:Textfield 不会失去对外部点击的关注

[英]Jetpack Compose: Textfield doenst lose focus on click outside of it

I am trying to implement a searchbar in my Compose app.我正在尝试在我的 Compose 应用程序中实现搜索栏。 I have a textfield, which I want to lose focus of and hide the keyboard, when I click outside of the textfield.我有一个文本字段,当我在文本字段之外单击时,我想失去焦点并隐藏键盘。 However, I can't figure out how to do it.但是,我不知道该怎么做。 I did try to do it this way, which I saw on github.我确实尝试过这样做,我在 github 上看到了。

However, i did some changes.然而,我做了一些改变。 The original solution used this part of code isHintDisplayed = it.= FocusState Active which seem to be deprecated.原始解决方案使用这部分代码isHintDisplayed = it.= FocusState Active似乎已被弃用。 So I changed it to isHintDisplayed = it.isFocused = true which should in theory do the same.所以我将其更改为isHintDisplayed = it.isFocused = true理论上应该这样做。 If I revert back to older versions of compose and use FocusState.Active, the focus/unfocus works perfectly, but I can't get it to work with my code.如果我恢复到旧版本的 compose 并使用 FocusState.Active,焦点/取消焦点可以完美地工作,但我无法让它与我的代码一起使用。

Any ideas?有任何想法吗?

here is my code:这是我的代码:

@Composable
fun ListScreen(
    navController: NavController
) {
    Surface(
        color = MaterialTheme.colors.background,
        modifier = Modifier.fillMaxSize()
    ) {
        Column {
            Spacer(modifier = Modifier.height(20.dp))
            Image(
                painter = painterResource(id = R.drawable.ic_international_pok_mon_logo),
                contentDescription = "Cards",
                modifier = Modifier
                    .fillMaxWidth()
                    .align(CenterHorizontally)
            )
            SearchBar(
                hint = "Search",
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp)
            ) {

            }
        }
    }
}

And here is Searchbar:这是搜索栏:

@Composable
fun SearchBar(
    modifier: Modifier = Modifier,
    hint: String = "",
    onSearch: (String) -> Unit = {}
) {
    var text by remember {
        mutableStateOf("")
    }
    var isHintDisplayed by remember {
        mutableStateOf(false)
    }

    Box(modifier = modifier) {
        BasicTextField(
            value = text,
            onValueChange = {
                text = it
                onSearch(it)
            },
            maxLines = 1,
            singleLine = true,
            textStyle = TextStyle(color = Color.Black),
            modifier = Modifier
                .fillMaxWidth()
                .shadow(5.dp, CircleShape)
                .background(Color.White, CircleShape)
                .padding(horizontal = 20.dp, vertical = 12.dp)
                .onFocusChanged {
                    isHintDisplayed = it.isFocused != true
                }
        )
        if(isHintDisplayed) {
            Text(
                text = hint,
                color = Color.LightGray,
                modifier = Modifier
                    .padding(horizontal = 20.dp, vertical = 12.dp)
            )
        }
    }
}

If you want to hide keyboard and want to clear focus , you can do it by adding KeyboardOptions and KeyboardActions in your TextField.如果要隐藏键盘清除焦点,可以通过在 TextField 中添加KeyboardOptionsKeyboardActions来实现。 You can do it by adding any ImeAction you want, eg ImeAction.Search .您可以通过添加任何您想要的ImeAction来做到这一点,例如ImeAction.Search
If You want to hide keyboard on outside area click , then you can set a clickable modifier in your parent composable, and manage keyboard show hide state by a variable, state of which will be changed upon clicking parent composable.如果要在外部区域单击隐藏键盘,则可以在父可组合中设置可单击修饰符,并通过变量管理键盘显示隐藏 state,其中 state 将在单击父可组合时更改。
If you want to manage keyboard display option and focus state, by both keyboard action and outside area click, you can modify your code as below.如果你想管理键盘显示选项和焦点 state,通过键盘动作和外部区域点击,你可以修改你的代码如下。

@Composable
fun ListScreen() {
    Surface(
        color = MaterialTheme.colors.background,
        modifier = Modifier.fillMaxSize()
    ) {
        var hideKeyboard by remember { mutableStateOf(false) }
        Column(modifier = Modifier.clickable { hideKeyboard = true }) {
            Spacer(modifier = Modifier.height(20.dp))
            Image(
                painter = painterResource(id = R.drawable.ic_launcher_foreground),
                contentDescription = "Cards",
                modifier = Modifier
                    .fillMaxWidth()
                    .align(CenterHorizontally)
            )
            SearchBar(
                hint = "Search",
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp),
                hideKeyboard = hideKeyboard,
                onFocusClear = { hideKeyboard = false }
            ) {

            }
        }
    }
}


@Composable
fun SearchBar(
    modifier: Modifier = Modifier,
    hint: String = "",
    hideKeyboard: Boolean = false,
    onFocusClear: () -> Unit = {},
    onSearch: (String) -> Unit = {}
) {
    var text by remember {
        mutableStateOf("")
    }
    var isHintDisplayed by remember {
        mutableStateOf(false)
    }
    val focusManager = LocalFocusManager.current

    Box(modifier = modifier.background(color = Color.Red)) {
        BasicTextField(
            value = text,
            onValueChange = {
                text = it
                onSearch(it)
            },
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
            keyboardActions = KeyboardActions(onSearch = {
                focusManager.clearFocus()
                onSearch(text)
            }),
            maxLines = 1,
            singleLine = true,
            textStyle = TextStyle(color = Color.Black),
            modifier = Modifier
                .fillMaxWidth()
                .shadow(5.dp, CircleShape)
                .background(Color.White, CircleShape)
                .padding(horizontal = 20.dp, vertical = 12.dp)
                .onFocusChanged {
                    isHintDisplayed = it.hasFocus != true
                }
        )
        if(isHintDisplayed) {
            Text(
                text = hint,
                color = Color.LightGray,
                modifier = Modifier
                    .padding(horizontal = 20.dp, vertical = 12.dp)
            )
        }
    }

    if (hideKeyboard) {
        focusManager.clearFocus()
        // Call onFocusClear to reset hideKeyboard state to false
        onFocusClear()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM