Доступ к значению TextField из другой составной функции в Jetpack Compose

Я создал два TextField Пароль от электронной почты & ButtonАвторизоваться. Теперь, нажав эту кнопку, я хочу получить доступ к тексту и показать успех / ошибку на основе проверки.

Проблема в том, что они находятся в двух разных составных функциях.

      @Composable
    fun EmailField() {
        var email by remember { mutableStateOf("") }

        TextField(
            modifier = Modifier.fillMaxWidth(0.9f),
            colors = TextFieldDefaults.textFieldColors(
                textColor = Color.White,
                focusedIndicatorColor = Color.White,
                focusedLabelColor = Color.White
            ),
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") },
            leadingIcon = {
                Icon(
                    Icons.Filled.Email,
                    "contentDescription",
                    modifier = Modifier.clickable {})
            }
        )
    }

Кнопка:

      @Composable
    private fun LoginButton() {
        Button(
            onClick = {
                      // validate email and password here
            },
            colors = ButtonDefaults.buttonColors(
                backgroundColor = Color.Yellow,
                contentColor = Color.White
            )
        ) {
            Text(text = "Login")
        }
    }

Если вы хотите увидеть всю активность, вот как она структурирована на данный момент.

      class LoginActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            AppTheme {
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(color = MaterialTheme.colors.primary),
                    verticalArrangement = Arrangement.Top,
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Spacer(modifier = Modifier.height(32.dp))
                    LoginLogo()
                    Spacer(modifier = Modifier.height(32.dp))
                    Text(
                        text = "Login",
                        modifier = Modifier.fillMaxWidth(0.9f),
                        style = MaterialTheme.typography.h5,
                        textAlign = TextAlign.Start
                    )
                    Spacer(modifier = Modifier.height(12.dp))
                    Text(
                        text = "Please sign in to continue",
                        modifier = Modifier.fillMaxWidth(0.9f),
                        style = MaterialTheme.typography.subtitle1,
                        textAlign = TextAlign.Start
                    )
                    Spacer(modifier = Modifier.height(32.dp))
                    EmailField()
                    Spacer(modifier = Modifier.height(16.dp))
                    PassWordField()
                    Spacer(modifier = Modifier.height(16.dp))
                    LoginButton()
                }
            }
        }
    }

    @Composable
    private fun LoginButton() {
        Button(
            onClick = {
                      // validate email and password here
            },
            colors = ButtonDefaults.buttonColors(
                backgroundColor = Color.Yellow,
                contentColor = Color.White
            )
        ) {
            Text(text = "Login")
        }
    }

    @Composable
    fun LoginLogo() {
        Image(
            painter = painterResource(R.drawable.ic_vector_app_logo),
            contentDescription = "Login Logo",
            modifier = Modifier
                .width(120.dp)
                .height(120.dp)
        )
    }

    @Composable
    fun EmailField() {
        var email by remember { mutableStateOf("") }

        TextField(
            modifier = Modifier.fillMaxWidth(0.9f),
            colors = TextFieldDefaults.textFieldColors(
                textColor = Color.White,
                focusedIndicatorColor = Color.White,
                focusedLabelColor = Color.White
            ),
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") },
            leadingIcon = {
                Icon(
                    Icons.Filled.Email,
                    "contentDescription",
                    modifier = Modifier.clickable {})
            }
        )
    }

    @Composable
    fun PassWordField() {
        var password by rememberSaveable { mutableStateOf("") }

        TextField(
            modifier = Modifier.fillMaxWidth(0.9f),
            colors = TextFieldDefaults.textFieldColors(
                textColor = Color.White,
                focusedIndicatorColor = Color.White,
                focusedLabelColor = Color.White
            ),
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") },
            visualTransformation = PasswordVisualTransformation(),
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
            leadingIcon = {
                Icon(
                    Icons.Filled.Lock,
                    "contentDescription",
                    modifier = Modifier.clickable {})
            }
        )
    }


}

Как правильно обрабатывать значения в этом случае?

3 ответа

Вы можете использовать ViewModel или что-то вроде:

      class TextFieldState(){
    var text: String by mutableStateOf("")
}

@Composable
fun login(){

    var emailState = remember { TextFieldState() }

    EmailField(emailState)
    LoginButton( onValidate = { /** validate **/})

}

с участием:

      @Composable
fun EmailField( emailState : TextFieldState = remember { TextFieldState() }) {

    TextField(
        value = emailState.text,
        onValueChange = {
            emailState.text = it
        },
        //your code
   )
}

а также:

      @Composable
private fun LoginButton(onValidate: () -> Unit) {
    Button(
        onClick =  onValidate,
        //your code
    )
}

Вот еще одно решение с RememberSaveable

      @Composable
fun MainBody() {
Column(
    modifier = Modifier
        .fillMaxHeight()
        .fillMaxWidth()
) {
    var inputValue by rememberSaveable { mutableStateOf("") }
    CommonTextField(value = inputValue, onInputChanged = { inputValue = it })
}
}

И здесь определяется функция CommonTextField

       @Composable
 fun CommonTextField(value: String, onInputChanged: (String) -> Unit) {
 TextField(value = value,
    onValueChange = onInputChanged,
 modifier = Modifier
    .fillMaxWidth()
    .padding(16.dp),
label = { Text(text = "Enter here")})
}

Я достиг этого следующим образом: -

      @Composable
fun login(){
    var dataInput = "xyz@abc.com"
    EmailField(dataInput, onChange = { dataInput = it })
    LoginButton( onValidate = { /** validate **/})
}

@Composable
fun EmailField(textData: String, onChange: (String) -> Unit = {}) {
   var textInput by remember { mutableStateOf(textData) }    
   TextField(
       value = textInput,
       onValueChange = {
          textInput = it
          onChange(it)
       },
                //your code
     )
}

Прелесть этого в том, что он не будет перекомпоновывать все остальные представления снова при изменении ввода для любого TextField.

Другие вопросы по тегам