[go: nahoru, domu]

blob: 0751e096a8ece1a014a44f9dda52089f5de33568 [file] [log] [blame]
/*
* 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.foundation.text
import androidx.compose.foundation.Interaction
import androidx.compose.foundation.InteractionState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.TextLayoutResult
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.text.input.VisualTransformation
/**
* Basic composable that enables users to edit text via hardware or software keyboard, but
* provides no decorations like hint or placeholder.
*
* Whenever the user edits the text, [onValueChange] is called with the most up to date state
* represented by [String] with which developer is expected to update their state.
*
* Unlike [TextFieldValue] overload, this composable does not let the developer to control
* selection, cursor and text composition information. Please check [TextFieldValue] and
* corresponding [BasicTextField] overload for more information.
*
* It is crucial that the value provided in the [onValueChange] is fed back into [BasicTextField] in
* order to have the final state of the text being displayed.
*
* Example usage:
* @sample androidx.compose.foundation.samples.BasicTextFieldWithStringSample
*
* Please keep in mind that [onValueChange] is useful to be informed about the latest state of the
* text input by users, however it is generally not recommended to modify the value that you get
* via [onValueChange] callback. Any change to this value may result in a context reset and end
* up with input session restart. Such a scenario would cause glitches in the UI or text input
* experience for users.
*
* This composable provides basic text editing functionality, however does not include any
* decorations such as borders, hints/placeholder. A design system based implementation such as
* Material Design Filled text field is typically what is needed to cover most of the needs. This
* composable is designed to be used when a custom implementation for different design system is
* needed.
*
* For example, if you need to include a placeholder in your TextField, you can write a composable
* using the decoration box like this:
* @sample androidx.compose.foundation.samples.PlaceholderBasicTextFieldSample
*
* If you want to add decorations to your text field, such as icon or similar, and increase the
* hit target area, use the decoration box:
* @sample androidx.compose.foundation.samples.TextFieldWithIconSample
*
* @param value the input [String] text to be shown in the text field
* @param onValueChange the callback that is triggered when the input service updates the text. An
* updated text comes as a parameter of the callback
* @param modifier optional [Modifier] for this text field.
* @param enabled controls the enabled state of the [BasicTextField]. When `false`, the text
* field will be neither editable nor focusable, the input of the text field will not be selectable
* @param readOnly controls the editable state of the [BasicTextField]. When `true`, the text
* field can not be modified, however, a user can focus it and copy text from it. Read-only text
* fields are usually used to display pre-filled forms that user can not edit
* @param textStyle Style configuration that applies at character level such as color, font etc.
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
* @param keyboardActions when the input service emits an IME action, the corresponding callback
* is called. Note that this IME action may be different from what you specified in
* [KeyboardOptions.imeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
* maxLines attribute will be automatically set to 1.
* @param maxLines the maximum height in terms of maximum number of visible lines. Should be
* equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
* set to 1 if [singleLine] is set to true.
* @param visualTransformation The visual transformation filter for changing the visual
* representation of the input. By default no visual transformation is applied.
* @param onTextLayout Callback that is executed when a new text layout is calculated.
* @param onTextInputStarted Callback that is executed when the initialization has done for
* communicating with platform text input service, e.g. software keyboard on Android. Called with
* [SoftwareKeyboardController] instance which can be used for requesting input show/hide software
* keyboard.
* @param interactionState the [InteractionState] representing the different [Interaction]s
* present on this TextField. You can create and pass in your own remembered [InteractionState]
* if you want to read the [InteractionState] and customize the appearance / behavior of this
* TextField in different [Interaction]s.
* @param cursorBrush [Brush] to paint cursor with. If [SolidColor] with [Color.Unspecified]
* provided, there will be no cursor drawn
* @param decorationBox Composable lambda that allows to add decorations around text field, such
* as icon, placeholder, helper messages or similar, and automatically increase the hit target area
* of the text field. To allow you to control the placement of the inner text field relative to your
* decorations, the text field implementation will pass in a framework-controlled composable
* parameter "innerTextField" to the decorationBox lambda you provide. You must call
* innerTextField exactly once.
*/
@Composable
fun BasicTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
interactionState: InteractionState = remember { InteractionState() },
cursorBrush: Brush = SolidColor(Color.Black),
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
@Composable { innerTextField -> innerTextField() }
) {
var textFieldValueState by remember { mutableStateOf(TextFieldValue(text = value)) }
val textFieldValue = textFieldValueState.copy(text = value)
BasicTextField(
value = textFieldValue,
onValueChange = {
textFieldValueState = it
if (value != it.text) {
onValueChange(it.text)
}
},
modifier = modifier,
enabled = enabled,
readOnly = readOnly,
textStyle = textStyle,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
maxLines = maxLines,
visualTransformation = visualTransformation,
onTextLayout = onTextLayout,
onTextInputStarted = onTextInputStarted,
cursorBrush = cursorBrush,
interactionState = interactionState,
singleLine = singleLine,
decorationBox = decorationBox
)
}
/**
* Basic composable that enables users to edit text via hardware or software keyboard, but
* provides no decorations like hint or placeholder.
*
* Whenever the user edits the text, [onValueChange] is called with the most up to date state
* represented by [TextFieldValue]. [TextFieldValue] contains the text entered by user, as well
* as selection, cursor and text composition information. Please check [TextFieldValue] for the
* description of its contents.
*
* It is crucial that the value provided in the [onValueChange] is fed back into [BasicTextField] in
* order to have the final state of the text being displayed.
*
* Example usage:
* @sample androidx.compose.foundation.samples.BasicTextFieldSample
*
* Please keep in mind that [onValueChange] is useful to be informed about the latest state of the
* text input by users, however it is generally not recommended to modify the values in the
* [TextFieldValue] that you get via [onValueChange] callback. Any change to the values in
* [TextFieldValue] may result in a context reset and end up with input session restart. Such
* a scenario would cause glitches in the UI or text input experience for users.
*
* This composable provides basic text editing functionality, however does not include any
* decorations such as borders, hints/placeholder. A design system based implementation such as
* Material Design Filled text field is typically what is needed to cover most of the needs. This
* composable is designed to be used when a custom implementation for different design system is
* needed.
*
* For example, if you need to include a placeholder in your TextField, you can write a composable
* using the decoration box like this:
* @sample androidx.compose.foundation.samples.PlaceholderBasicTextFieldSample
*
*
* If you want to add decorations to your text field, such as icon or similar, and increase the
* hit target area, use the decoration box:
* @sample androidx.compose.foundation.samples.TextFieldWithIconSample
*
* @param value The [androidx.compose.ui.text.input.TextFieldValue] to be shown in the
* [BasicTextField].
* @param onValueChange Called when the input service updates the values in [TextFieldValue].
* @param modifier optional [Modifier] for this text field.
* @param enabled controls the enabled state of the [BasicTextField]. When `false`, the text
* field will be neither editable nor focusable, the input of the text field will not be selectable
* @param readOnly controls the editable state of the [BasicTextField]. When `true`, the text
* field can not be modified, however, a user can focus it and copy text from it. Read-only text
* fields are usually used to display pre-filled forms that user can not edit
* @param textStyle Style configuration that applies at character level such as color, font etc.
* @param keyboardOptions software keyboard options that contains configuration such as
* [KeyboardType] and [ImeAction].
* @param keyboardActions when the input service emits an IME action, the corresponding callback
* is called. Note that this IME action may be different from what you specified in
* [KeyboardOptions.imeAction].
* @param singleLine when set to true, this text field becomes a single horizontally scrolling
* text field instead of wrapping onto multiple lines. The keyboard will be informed to not show
* the return key as the [ImeAction]. Note that [maxLines] parameter will be ignored as the
* maxLines attribute will be automatically set to 1.
* @param maxLines the maximum height in terms of maximum number of visible lines. Should be
* equal or greater than 1. Note that this parameter will be ignored and instead maxLines will be
* set to 1 if [singleLine] is set to true.
* @param visualTransformation The visual transformation filter for changing the visual
* representation of the input. By default no visual transformation is applied.
* @param onTextLayout Callback that is executed when a new text layout is calculated.
* @param onTextInputStarted Callback that is executed when the initialization has done for
* communicating with platform text input service, e.g. software keyboard on Android. Called with
* [SoftwareKeyboardController] instance which can be used for requesting input show/hide software
* keyboard.
* @param interactionState The [InteractionState] representing the different [Interaction]s
* present on this TextField. You can create and pass in your own remembered [InteractionState]
* if you want to read the [InteractionState] and customize the appearance / behavior of this
* TextField in different [Interaction]s.
* @param cursorBrush [Brush] to paint cursor with. If [SolidColor] with [Color.Unspecified]
* provided, there will be no cursor drawn
* @param decorationBox Composable lambda that allows to add decorations around text field, such
* as icon, placeholder, helper messages or similar, and automatically increase the hit target area
* of the text field. To allow you to control the placement of the inner text field relative to your
* decorations, the text field implementation will pass in a framework-controlled composable
* parameter "innerTextField" to the decorationBox lambda you provide. You must call
* innerTextField exactly once.
*/
@Composable
fun BasicTextField(
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
interactionState: InteractionState = remember { InteractionState() },
cursorBrush: Brush = SolidColor(Color.Black),
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
@Composable { innerTextField -> innerTextField() }
) {
CoreTextField(
value = value,
onValueChange = onValueChange,
modifier = modifier,
textStyle = textStyle,
visualTransformation = visualTransformation,
onTextLayout = onTextLayout,
interactionState = interactionState,
onTextInputStarted = onTextInputStarted,
cursorBrush = cursorBrush,
imeOptions = keyboardOptions.toImeOptions(singleLine = singleLine),
keyboardActions = keyboardActions,
softWrap = !singleLine,
maxLines = if (singleLine) 1 else maxLines,
decorationBox = decorationBox,
enabled = enabled,
readOnly = readOnly
)
}