JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.27k stars 1.18k forks source link

how to use enter key with DropdownMenu when (focusable=false) #1573

Closed helmysaeed closed 1 month ago

helmysaeed commented 2 years ago

I need to use DropdownMenu with OutlinedTextField to make a search box and use nav tab with enter key it work with a click but not with enter or tab key

akurasov commented 2 years ago

It is a bit hard to understand what is wrong. Could you please describe scenario as a sequence. Like

  1. Click on textField
  2. input abc
  3. press enter .....
helmysaeed commented 2 years ago

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

// 1- I need to filter items by OutlinedTextField // 2- navigate the items by keys up and down and print the selected item by Enter key

var expanded by remember { mutableStateOf(false) }
var items     =  remember {  mutableStateListOf("apple", "banana", "egg")}
var item2    =  remember {  mutableStateListOf("")}
  var  name = remember { mutableStateOf( TextFieldValue("")) }
item2= items.filter { it.contains(name.value.text) }.toMutableStateList()
val keyEvent: (ks:KeyEvent,s:String) -> Boolean = {
    ks,s->
    if (ks.key == Key.Enter) {
        println(s.toString())
    }
    true
}

Box(modifier = Modifier.fillMaxSize().wrapContentSize()) {
    OutlinedTextField(value = name.value.text, onValueChange = {

        name.value = TextFieldValue(it)

        println("" + name.value.text + items.toMutableList().toString())
        expanded = true

    })
    DropdownMenu(
        // if    focusable = true    it will block input in   OutlinedTextField
        focusable = false,
        expanded = expanded,
        onDismissRequest = { expanded = false },
        modifier = Modifier.fillMaxWidth()
    ) {
        item2.forEachIndexed { index, s ->
            DropdownMenuItem(onClick = {

            }, modifier = Modifier.onPreviewKeyEvent {
                keyEvent(it, s)
            }) {

                Text(text = s)
            }
        }
    }
}

}

@akurasov

akurasov commented 2 years ago

You can have focus either on DDW or on TextField. So probably you should make it focusable =true and move focus between them depending on which keys are entered.

Another option, make it focusable=false and handle arrows and enter key on the text field, managing DDW state.

helmysaeed commented 2 years ago

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

//  1- I need to filter items by OutlinedTextField
// 2-  navigate the items by keys up and down  and  print the   selected item by  Enter key

val (first, second) = FocusRequester.createRefs()
var expanded by remember { mutableStateOf(false) }
var isFouced by remember { mutableStateOf(true) }
var isEnable by remember { mutableStateOf(true) }
var items = remember { mutableStateListOf("apple", "banana", "egg") }
var item2 = remember { mutableStateListOf("") }
var name = remember { mutableStateOf(TextFieldValue("")) }
var na: (n: String) -> Unit = {

        it ->
    name.value = TextFieldValue(it)
    expanded=true
    println(
        "na" + name.value.text
    )
}
item2 = items.filter { it.contains(name.value.text) }.toMutableStateList()
val keyEvent: (ks: KeyEvent, s: String) -> Boolean = { ks, s ->
    when {
        (ks.key == Key.DirectionDown && ks.type == KeyEventType.KeyDown ||ks.key == Key.Tab && ks.type == KeyEventType.KeyDown) -> {
            isFouced = true
            isEnable=false
            println("down" + isFouced)
            true
        }
        (ks.key != Key.DirectionDown&& ks.type == KeyEventType.KeyDown) -> {
            isFouced = false
             isEnable=true

            println("up" + isFouced)
            true
        }
        else -> false

    }
}

Box(modifier = Modifier.fillMaxSize().wrapContentSize()) {
    OutlinedTextField(value = name.value.text, onValueChange = {

        na(it)

    },
        modifier = Modifier.onPreviewKeyEvent {

            keyEvent(it, "")
        }.focusOrder(first) { down = second }, singleLine = true , enabled =isEnable )

        DropdownMenu(
            // if    focusable = true    it will block input in   OutlinedTextField
            focusable = isFouced,
            expanded = expanded,
            onDismissRequest = { expanded = false },
            modifier = Modifier.fillMaxWidth()
        ) {
            item2.forEachIndexed { index, s ->
                DropdownMenuItem(onClick = {

                }, modifier = Modifier
                .fillMaxWidth().focusOrder(second)) {

                    Text(text = s)
                }
            }
        }

}

} @akurasov I try every thing but doesn't work

okushnikov commented 2 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.