diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/TextFields.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/TextFields.kt index 7070bf28c15b9..e223f97348cae 100644 --- a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/TextFields.kt +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/TextFields.kt @@ -20,6 +20,8 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material.TextField import androidx.compose.mpp.demo.Screen +import androidx.compose.mpp.demo.textfield.android.CapitalizationAutoCorrectDemo +import androidx.compose.mpp.demo.textfield.android.KeyboardTypeDemo import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -31,6 +33,12 @@ val TextFields = Screen.Selection( Screen.Example("AlmostFullscreen") { AlmostFullscreen() }, + Screen.Example("Android Capitalization/AutoCorrect") { + CapitalizationAutoCorrectDemo() + }, + Screen.Example("Android Keyboard Types") { + KeyboardTypeDemo() + }, ) @Composable diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/CapitalizationAutoCorrectDemo.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/CapitalizationAutoCorrectDemo.kt new file mode 100644 index 0000000000000..76a1c0eab88f8 --- /dev/null +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/CapitalizationAutoCorrectDemo.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.mpp.demo.textfield.android + +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.dp + +private val KeyboardOptionsList = listOf( + ImeOptionsData( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + capitalization = KeyboardCapitalization.Characters + ), + + name = "Capitalize Characters" + ), + ImeOptionsData( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + capitalization = KeyboardCapitalization.Words + ), + name = "Capitalize Words" + ), + ImeOptionsData( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + capitalization = KeyboardCapitalization.Sentences + ), + name = "Capitalize Sentences" + ), + ImeOptionsData( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + autoCorrect = true + ), + name = "AutoCorrect On" + ), + ImeOptionsData( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + autoCorrect = false + ), + name = "AutoCorrect Off" + ) +) + +@Composable +fun CapitalizationAutoCorrectDemo() { + LazyColumn { + items(KeyboardOptionsList) { data -> + TagLine(tag = data.name) + MyTextField(data) + } + } +} + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +private fun MyTextField(data: ImeOptionsData) { + var state by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue()) + } + val keyboardController = LocalSoftwareKeyboardController.current + BasicTextField( + modifier = demoTextFieldModifiers.defaultMinSize(100.dp), + value = state, + keyboardOptions = data.keyboardOptions, + keyboardActions = KeyboardActions { keyboardController?.hide() }, + onValueChange = { state = it }, + textStyle = TextStyle(fontSize = fontSize8), + cursorBrush = SolidColor(Color.Red) + ) +} \ No newline at end of file diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/ComposeText.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/ComposeText.kt new file mode 100644 index 0000000000000..04a46f8ac4d42 --- /dev/null +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/ComposeText.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.mpp.demo.textfield.android + +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.sp + +private const val longText = "This is a very-very long string that wraps into a few lines " + + "given the width restrictions." +const val displayText = "Text Demo" +const val displayTextChinese = "文本演示" +const val displayTextArabic = "\u0639\u0631\u0636\u0020\u0627\u0644\u0646\u0635" +const val displayTextHindi = "पाठ डेमो" +const val displayTextBidi = "Text \u0639\u0631\u0636" + +val fontSize4 = 16.sp +val fontSize6 = 20.sp +val fontSize8 = 25.sp +val fontSize10 = 30.sp + +@Composable +fun TagLine(tag: String) { + Text( + style = TextStyle(fontSize = fontSize8), + text = buildAnnotatedString { + append("\n") + withStyle( + style = SpanStyle( + color = Color(0xFFAAAAAA), + fontSize = fontSize6 + ) + ) { + append(tag) + } + } + ) +} \ No newline at end of file diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/InputFieldDemo.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/InputFieldDemo.kt new file mode 100644 index 0000000000000..5c1f0333f4810 --- /dev/null +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/InputFieldDemo.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.mpp.demo.textfield.android + +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp + +@Composable +fun InputFieldDemo() { + LazyColumn { + item { + TagLine(tag = "LTR Layout") + } + item { + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) { + Column(modifier = Modifier.fillMaxWidth()) { + TagLine(tag = "simple editing single line") + EditLine(singleLine = true) + TagLine(tag = "simple editing multi line") + EditLine(text = displayTextHindi) + TagLine(tag = "simple editing RTL") + EditLine(text = displayTextArabic) + } + } + } + item { + TagLine(tag = "RTL Layout") + } + item { + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + Column(modifier = Modifier.fillMaxWidth()) { + TagLine(tag = "simple editing RTL") + EditLine() + EditLine(text = displayTextArabic) + EditLine(text = displayText) + } + } + } + } +} + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +internal fun EditLine( + keyboardType: KeyboardType = KeyboardType.Text, + imeAction: ImeAction = ImeAction.Default, + singleLine: Boolean = false, + text: String = "" +) { + val keyboardController = LocalSoftwareKeyboardController.current + val state = rememberSaveable { mutableStateOf(text) } + BasicTextField( + modifier = demoTextFieldModifiers, + value = state.value, + singleLine = singleLine, + keyboardOptions = KeyboardOptions( + keyboardType = keyboardType, + imeAction = imeAction + ), + keyboardActions = KeyboardActions { keyboardController?.hide() }, + onValueChange = { state.value = it }, + textStyle = TextStyle(fontSize = fontSize8), + ) +} + +val demoTextFieldModifiers = Modifier + .padding(6.dp) + .border(1.dp, Color.LightGray, RoundedCornerShape(6.dp)) + .padding(6.dp) \ No newline at end of file diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/KeyboardSingleLineDemo.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/KeyboardSingleLineDemo.kt new file mode 100644 index 0000000000000..38251f5c7e28f --- /dev/null +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/KeyboardSingleLineDemo.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.mpp.demo.textfield.android + +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.dp + +internal class ImeOptionsData( + val keyboardOptions: KeyboardOptions, + val singleLine: Boolean = false, + val name: String, +) + +private val ImeOptionsList = listOf( + ImeOptionsData( + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text + ), + name = "singleLine/Text" + ), + ImeOptionsData( + singleLine = false, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text + ), + name = "multiLine/Text" + ), + ImeOptionsData( + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Search + ), + name = "singleLine/Text/Search" + ), + ImeOptionsData( + singleLine = false, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Search + ), + name = "multiLine/Text/Search" + ), + ImeOptionsData( + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number + ), + name = "singleLine/Number" + ), + ImeOptionsData( + singleLine = false, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number + ), + name = "multiLine/Number" + ), + ImeOptionsData( + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Send + ), + name = "singleLine/Number/Send" + ), + ImeOptionsData( + singleLine = false, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Send + ), + name = "multiLine/Number/Send" + ), + ImeOptionsData( + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Decimal + ), + name = "singleLine/Decimal" + ), + ImeOptionsData( + singleLine = false, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Decimal + ), + name = "multiLine/Decimal" + ) +) + +@Composable +fun ImeSingleLineDemo() { + LazyColumn { + items(ImeOptionsList) { + TagLine(tag = "${it.name}") + MyTextField(it) + } + } +} + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +private fun MyTextField(data: ImeOptionsData) { + val keyboardController = LocalSoftwareKeyboardController.current + val state = rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue()) + } + BasicTextField( + modifier = demoTextFieldModifiers.defaultMinSize(100.dp), + value = state.value, + keyboardOptions = data.keyboardOptions, + keyboardActions = KeyboardActions { keyboardController?.hide() }, + singleLine = data.singleLine, + onValueChange = { state.value = it }, + textStyle = TextStyle(fontSize = fontSize8), + cursorBrush = SolidColor(Color.Red) + ) +} \ No newline at end of file diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/TextFieldKeyboardTypeDemo.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/TextFieldKeyboardTypeDemo.kt new file mode 100644 index 0000000000000..af8e394e44967 --- /dev/null +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/textfield/android/TextFieldKeyboardTypeDemo.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.mpp.demo.textfield.android + + +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.input.KeyboardType + +@Composable +fun KeyboardTypeDemo() { + LazyColumn { + item { Item(KeyboardType.Text) } + item { Item(KeyboardType.Ascii) } + item { Item(KeyboardType.Number) } + item { Item(KeyboardType.Phone) } + item { Item(KeyboardType.Uri) } + item { Item(KeyboardType.Email) } + item { Item(KeyboardType.Password) } + item { Item(KeyboardType.NumberPassword) } + } +} + +@Composable +private fun Item(keyboardType: KeyboardType) { + TagLine(tag = "Keyboard Type: $keyboardType") + EditLine(keyboardType = keyboardType) +}