OutlineTextField , TextField not working in Jetpack Compose 1.0.0-alpha02 - android

For some reason, CoreTextField works but TextField and OutlineTextField wont
Works
#Composable
fun TextFieldDemo(){
val text = remember { mutableStateOf(TextFieldValue("Text")) }
CoreTextField(modifier = Modifier.fillMaxWidth(),
value = text.value,
onValueChange = {text.value = it})
}
Not working
#Composable
fun TextFieldDemo(){
val text = remember { mutableStateOf(TextFieldValue("Text")) }
OutlinedTextField(value = text.value,
onValueChange = {text.value = it}, label = {Text("Test")})
}
Error: Non of the following Functions can be called for OutlinedTextField
From the docs change
Bug Fixes
androidx.ui.foundation.TextFieldValue and androidx.ui.input.EditorValue are deprecated. TextField, FilledTextField and CoreTextField composables that uses that type is also deprecated. Please use androidx.ui.input.TextFieldValue instead (I4066d, b/155211005)
But I'm using what it says (I think)
Edit

You are missing the "label" param in the original question, as we can see in the image. Following Gabriele's comment made it work, so you shouldn't change the question with the answer, it's a lot confusing.
Just for the record, here it`s the code that works in 1.0.0-alpha02:
#Composable
fun TextFieldDemo() {
val text = remember { mutableStateOf(TextFieldValue("Text")) }
OutlinedTextField(value = text.value,
onValueChange = { text.value = it },
label = { Text("Test") })
}

Related

Jetpack Compose delete TextField content with icon

I'm trying to make a custom TextField where the text gets deleted when the right icon is pressed. The problem with the following code is that the textFieldValue.text is a val, so it can't be reassigned.
So far the only solution I have found is to recompose the entire TextField sending "" as the text. Is there a better way to achieve this?
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver)
{ mutableStateOf(TextFieldValue("")) }
MyTextField(
text = textFieldValue,
onValueChange = {
textFieldValue = it
},
leftIconClickable = { /*Do nothing*/ },
rightIconClickable = { textFieldValue.text = "" }
)
(At this point this textField has almost the same code as the TextField of Jetpack Compose, the main difference being that it also receives 2 clickables for the icons)
Have your tried performing a copy()?
rightIconClickable = { textFieldValue = textFieldValue.copy(text = "") }
Here's a sample of a TextField using TextFieldValue with a simple Button where I copy() the current TextFieldValue instance, re-assigning it to the same variable, and it clears the TextField.
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue(""))
}
Column {
TextField(
value = textFieldValue,
onValueChange = {
textFieldValue = it
}
)
Button(onClick = {
textFieldValue = textFieldValue.copy(text = "")}) {
}
}

Strange scroll in the BasicTextField with IntrinsicSize.Min

I need to implement UI control(decrease button, resizeable text input, increase button)
I was trying both ways - compose and XML version.
Compose version.
I have a strange scroll when I click on BasicTextField and pull horizontally. It just hides TextField value.
BasicTextField(
value = text,
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
keyboardActions = remember { KeyboardActions(onDone = { keyboardController?.hide() }) },
onValueChange = { onTextChanged(it) },
singleLine = true,
decorationBox = { innerTextField ->
Box(modifier = Modifier.width(IntrinsicSize.Min)) {
innerTextField()
}
}
)
Modifier.width(1.dp, Dp.Infinity), doesn't help and takes empty horizontal padding, but it doesn't have the "internal" scroll.
1.1. How to fix the "internal" scroll in the BasicTextField with applied IntrinsicSize.Min?
1.2. Also BasicTextField cuts the left-most digit when you put cursor position. It would be great to have the same behavior as we have in the XML version.
XML version.
I was trying to use the XML version with EditText instead of Compose BasicTextField but stuck with merge compose state and EditText TextWatcher listener.
2.1. To avoid twice setting the same text value to the EditText, I should compare compose state value and EditText value each time in the update {} block, is that ok? Or here can be a better solution?
AndroidView(
factory = {
_binding = L7Binding.inflate(inflater, container, false)
val view = _binding!!.root
_binding!!.editText.doOnTextChanged { text, _, _, _ ->
viewModel.onTextChanged(text.toString())
}
view
},
update = {
if (_binding!!.editText.text.toString() != inputText) {
_binding!!.editText.setText(inputText)
}
}
)
I faced the same problem.
Solved it with the help of this code, I hope it will be useful to you)
BasicTextField(,
modifier = Modifier
.disabledHorizontalPointerInputScroll()...
and also
private val HorizontalScrollConsumer = object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource) = available.copy(y = 0f)
override suspend fun onPreFling(available: Velocity) = available.copy(y = 0f)
}
fun Modifier.disabledHorizontalPointerInputScroll(disabled: Boolean = true) =
if (disabled) this.nestedScroll(HorizontalScrollConsumer) else this

TextField is overlapped by keyboard in Android Compose

I have a TextField in column with verticalScroll().
When adding a large number of characters, the textfield size goes beyond the keyboard and I stop seeing what I am typing
I tried to use this lib, but that's doesn't help
I think you can use BringIntoViewRequester in your TextField.
var state by rememberSaveable {
mutableStateOf("")
}
val coroutineScope = rememberCoroutineScope()
val bringIntoViewRequester = remember {
BringIntoViewRequester()
}
TextField(
value = state,
onValueChange = { text ->
state = text
// This will cause the TextField be repositioned on the screen
// while you're typing
coroutineScope.launch {
bringIntoViewRequester.bringIntoView()
}
},
modifier = Modifier
.bringIntoViewRequester(bringIntoViewRequester)
.onFocusChanged {
if (it.isFocused) {
coroutineScope.launch {
delay(400) // delay to way the keyboard shows up
bringIntoViewRequester.bringIntoView()
}
}
},
)
See the complete sample here.
you can add android:ellipsize="end" and android:maxLines="1" or whatever lines you want, in your text xml hope it would be helpful.

AutoLink for Android Compose Text

Is there any way to use android:autoLink feature on JetPack Compose Text?
I know, that it is maybe not "declarative way" for using this feature in one simple tag/modifier, but maybe there is some easy way for this?
For styling text I can use this way
val apiString = AnnotatedString.Builder("API provided by")
apiString.pushStyle(
style = SpanStyle(
color = Color.Companion.Blue,
textDecoration = TextDecoration.Underline
)
)
apiString.append("https://example.com")
Text(text = apiString.toAnnotatedString())
But, how can I manage clicks here? And would be great, if I programatically say what behaviour I expect from the system (email, phone, web, etc). Like it. works with TextView.
Thank you
We can achieve Linkify kind of TextView in Android Compose like this example below,
#Composable
fun LinkifySample() {
val uriHandler = UriHandlerAmbient.current
val layoutResult = remember {
mutableStateOf<TextLayoutResult?>(null)
}
val text = "API provided by"
val annotatedString = annotatedString {
pushStyle(
style = SpanStyle(
color = Color.Companion.Blue,
textDecoration = TextDecoration.Underline
)
)
append(text)
addStringAnnotation(
tag = "URL",
annotation = "https://example.com",
start = 0,
end = text.length
)
}
Text(
fontSize = 16.sp,
text = annotatedString, modifier = Modifier.tapGestureFilter { offsetPosition ->
layoutResult.value?.let {
val position = it.getOffsetForPosition(offsetPosition)
annotatedString.getStringAnnotations(position, position).firstOrNull()
?.let { result ->
if (result.tag == "URL") {
uriHandler.openUri(result.item)
}
}
}
},
onTextLayout = { layoutResult.value = it }
)
}
In the above example, we can see we give the text and also we use addStringAnnotation to set the tag. And using tapGestureFilter, we can get the clicked annotation.
Finally using UriHandlerAmbient.current we can open the link like email, phone, or web.
Reference : https://www.hellsoft.se/rendering-markdown-with-jetpack-compose/
The most important part of jetpack compose is the compatibility with native android components.
Create a component that use TextView and use it:
#Composable
fun DefaultLinkifyText(modifier: Modifier = Modifier, text: String?) {
val context = LocalContext.current
val customLinkifyTextView = remember {
TextView(context)
}
AndroidView(modifier = modifier, factory = { customLinkifyTextView }) { textView ->
textView.text = text ?: ""
LinkifyCompat.addLinks(textView, Linkify.ALL)
Linkify.addLinks(textView, Patterns.PHONE,"tel:",
Linkify.sPhoneNumberMatchFilter, Linkify.sPhoneNumberTransformFilter)
textView.movementMethod = LinkMovementMethod.getInstance()
}
}
How to use:
DefaultLinkifyText(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
text = "6999999 and https://stackoverflow.com/ works fine"
)

TextField with Kotlin StateFlow

I'd like to have a TextField bound to a MutableStateFlow that comes from a view model. This is how I set it up:
#Composable
fun MyTextField(textFlow: MutableStateFlow<String>) {
val state = textFlow.collectAsState(initial = "")
TextField(
value = TextFieldValue(state.value),
onValueChange = { textFlow.value = it.text },
label = { Text(text = "Label") }
)
}
When I type something into the text field, it behaves really strangely. For example, if I type 'asd', it ends up with 'asdasa'. How can I update textFlow.value without messing up with the text field?
This error is caused by the usage of TextFieldValue with Flow.
To fix this, set the value of the TextField to just state.value and then on text change set the value with textFlow.value = it.
#Composable
fun MyTextField(textFlow: MutableStateFlow<String>) {
val state = textFlow.collectAsState(initial = "")
TextField(
value = state.value,
onValueChange = { textFlow.value = it },
label = { Text(text = "Label") }
)
}

Categories

Resources