benjamin-luescher / compose-form

Android Jetpack Compose Form
MIT License
36 stars 10 forks source link

How to use Material Text Field instead your own? #5

Closed myxzlpltk closed 10 months ago

benjamin-luescher commented 1 year ago

You can create your own fields. Just copy a field from ch.benlu.composeform.fields.* and create your own.

In your scenario you have to create your own TextField (according to ch.benlu.composeform.fields.TextField) https://github.com/benjamin-luescher/compose-form/blob/main/composeform/src/main/java/ch/benlu/composeform/fields/TextField.kt

Below is an example of an own TextField using Material 3:

import android.annotation.SuppressLint
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
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.VisualTransformation
import androidx.compose.ui.unit.dp
import ch.benlu.composeform.Field
import ch.benlu.composeform.FieldState
import ch.benlu.composeform.Form

class M3TextField(
    label: String,
    form: Form,
    modifier: Modifier? = Modifier,
    fieldState: FieldState<String?>,
    isVisible: Boolean = true,
    isEnabled: Boolean = true,
    imeAction: ImeAction = ImeAction.Next,
    formatter: ((raw: String?) -> String)? = null,
    keyboardType: KeyboardType = KeyboardType.Text,
    visualTransformation: VisualTransformation = VisualTransformation.None
) : Field<String>(
    label = label,
    form = form,
    fieldState = fieldState,
    isVisible = isVisible,
    isEnabled = isEnabled,
    modifier = modifier,
    imeAction = imeAction,
    formatter = formatter,
    keyboardType = keyboardType,
    visualTransformation = visualTransformation
) {

    /**
     * Returns a composable representing the DateField / Picker for this field
     */
    @OptIn(ExperimentalMaterial3Api::class)
    @SuppressLint("NotConstructor")
    @Composable
    override fun Field() {
        this.updateComposableValue()
        if (!isVisible) {
            return
        }

        Column {
            // change the textfield here to whatever field you want - the following code represents the current implementation from the library
            OutlinedTextField(
                modifier = Modifier
                    .fillMaxWidth(),
                value = formatter?.invoke(value.value) ?: (value.value ?: ""),
                onValueChange = {
                    onChange(it, form)
                },
                keyboardOptions = KeyboardOptions(imeAction = imeAction ?: ImeAction.Next, keyboardType = keyboardType),
                keyboardActions = KeyboardActions.Default,
                enabled = isEnabled,
                isError = fieldState.hasError(),
                label = { Text(label) },
                interactionSource = remember { MutableInteractionSource() },
                visualTransformation = visualTransformation,
                placeholder = null
            )
            if (fieldState.hasError()) {
                Text(
                    text = fieldState.errorText.joinToString("\n"),
                    modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
                    style = TextStyle.Default.copy(color = MaterialTheme.colorScheme.error)
                )
            }
        }
    }
}

Just replace the OutlinedTextField by whatever textfield you'd like. And use the field in your form composable:

M3TextField(
  label = "my new field",
  form = form,
  fieldState = form.myNewField
).Field()