Fatima Jamal
Fatima Jamal

Reputation: 159

How to request focus and show keyboard on Textfield on specific pages of HorizontalPager?

I'm creating a signup page using HorizontalPager, where i have a textfield in three pages(one for email, username, password), and a date picker and ExposedDropdownMenuBox for gender.

I want to show keyboard on pages that have textfields only, and hide elsewhere.

I were only able to show keyboard on first page, but not the reset.

Here is the full code.

fun SignupPage(
    modifier: Modifier = Modifier,
    navController: NavController,
    navigateBack: () -> Unit,// authViewModel: AuthViewModel
) {
    var email by remember {
        mutableStateOf("")
    }
    var password by remember { mutableStateOf("") }
    var dateOfBirth by remember { mutableStateOf("") }
    var gender by remember { mutableStateOf("") }
    var isExpanded by remember {mutableStateOf(false)}
    var userName by remember { mutableStateOf("") }
    var colorButton by remember { mutableStateOf(Color.White) }


    val pages = registerInfoList.size
    val pagerState = rememberPagerState(pageCount = { pages })
    val scope = rememberCoroutineScope()
    var showPassword by remember {
        mutableStateOf(false)
    }
    var currentInput by remember { mutableStateOf("") }
    // To handle whether we can move to the next page
    val isFormValid = remember {
        derivedStateOf {
            when (pagerState.currentPage) {
                0 -> {
                    email.isNotEmpty()
                }
                1 -> {
                    password.isNotEmpty()
                }
                2 -> {
                    dateOfBirth.isNotEmpty()
                }
                3 -> {
                    gender.isNotEmpty()
                }
                4 -> {
                    userName.isNotEmpty()
                }
                else -> {
                   false
                }
            }
        }
    }


    val emailFocusRequester = remember {
        FocusRequester()
    }

    val showKeyboard = remember { mutableStateOf(true) }
    val keyboard = LocalSoftwareKeyboardController.current

    LaunchedEffect(key1=emailFocusRequester) {
        if(showKeyboard.value){
            emailFocusRequester.requestFocus()
            delay(100)
            keyboard?.show()
        }
    }



    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(
                title = {
                    Text(
                        "Create account",
                        fontWeight = FontWeight.Bold
                    )
                },
                navigationIcon = {
                    IconButton(onClick = {
                        scope.launch {
                            pagerState.animateScrollToPage(pagerState.currentPage - 1)
                        }

                    }) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.ArrowBack,
                            contentDescription = "Localized description"
                        )
                    }
                }, colors = TopAppBarColors(
                    containerColor = colorResource(id = R.color.black),
                    titleContentColor = Color.White,
                    actionIconContentColor = Color.White,
                    navigationIconContentColor = Color.White,
                    scrolledContainerColor = colorResource(id = R.color.black)
                )
            )
        },
    ) { innerPadding ->


        Column(
            modifier = modifier
                .fillMaxSize()
                .padding(innerPadding)
                .padding(8.dp),
            verticalArrangement = Arrangement.Top,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            HorizontalPager(
                state = pagerState,
                userScrollEnabled = false
            ) { index ->

                currentInput = when (index) {
                    0 -> email
                    1 -> password
                    2 -> dateOfBirth
                    3 -> gender
                    4 -> userName
                    else -> throw IllegalStateException("Unexpected page index")
                }

                Column(
                    modifier = Modifier
                        .padding(8.dp)
                        .wrapContentHeight()
                        .background(MaterialTheme.colorScheme.background),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(
                        modifier = Modifier.fillMaxWidth(),
                        textAlign = TextAlign.Start, // Aligns text to the left
                        text = registerInfoList[index].title,
                        fontSize = 20.sp,
                        fontWeight = FontWeight.Bold,
                        color = Color.White
                    )
                    Spacer(modifier = Modifier.size(4.dp))
                    when (index) {
                        0, 4 -> // email and name

                            TextField(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .focusRequester(emailFocusRequester
                                    )
                                ,
                                value = currentInput,
                                colors = TextFieldDefaults.colors(
                                    unfocusedContainerColor = colorResource(id = R.color.gray),
                                    cursorColor = colorResource(id = R.color.light_gray),
                                    focusedTextColor = Color.White,
                                    unfocusedTextColor = Color.White,
                                    focusedContainerColor = colorResource(id = R.color.moon_gray),
                                    disabledLabelColor = colorResource(id = R.color.moon_gray),
                                    focusedIndicatorColor = Color.Transparent,
                                    unfocusedIndicatorColor = Color.Transparent
                                ),
                                onValueChange = { newValue ->
                                    when (index) {
                                        0 -> email = newValue
                                        4 -> userName = newValue
                                    }
                                },
                                shape = RoundedCornerShape(8.dp),
                                singleLine = true,
                                keyboardOptions = KeyboardOptions(
                                    imeAction = ImeAction.Next
                                )
                            )

                        1 -> {
                            TextField(modifier = Modifier
                                .fillMaxWidth(),
                                value = password,
                                onValueChange = { password = it },
                                colors = TextFieldDefaults.colors(
                                    unfocusedContainerColor = colorResource(id = R.color.gray),
                                    cursorColor = colorResource(id = R.color.light_gray),
                                    focusedTextColor = Color.White,
                                    unfocusedTextColor = Color.White,
                                    focusedContainerColor = colorResource(id = R.color.moon_gray),
                                    disabledLabelColor = colorResource(id = R.color.moon_gray),
                                    focusedIndicatorColor = Color.Transparent,
                                    unfocusedIndicatorColor = Color.Transparent
                                ),
                                visualTransformation = if (showPassword) {

                                    VisualTransformation.None

                                } else {

                                    PasswordVisualTransformation()

                                },
                                keyboardOptions = KeyboardOptions(
                                    keyboardType = KeyboardType.Password,
                                    imeAction = ImeAction.Done
                                ),
                                shape = RoundedCornerShape(8.dp),
                                singleLine = true,
                                trailingIcon = {
                                    if (showPassword) {
                                        IconButton(onClick = { showPassword = false }) {
                                            Icon(
                                                imageVector = Icons.Filled.Visibility,
                                                contentDescription = "hide_password"
                                            )
                                        }
                                    } else {
                                        IconButton(
                                            onClick = { showPassword = true }) {
                                            Icon(
                                                imageVector = Icons.Filled.VisibilityOff,
                                                contentDescription = "hide_password"
                                            )
                                        }
                                    }
                                }
                            )
                        }

                        2 -> {

                            DatePicker{date ->
                                dateOfBirth = date.let {
                                    SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(it)
                                }
                            }
                        }
                        3 -> {
                            ExposedDropdownMenuBox(expanded = isExpanded,
                                onExpandedChange = {isExpanded = it}) {
                                TextField(
                                    value = gender,
                                    onValueChange = {},
                                    readOnly = true,
                                    trailingIcon = {ExposedDropdownMenuDefaults.TrailingIcon(expanded = isExpanded)},
                                    colors = ExposedDropdownMenuDefaults.textFieldColors(
                                        unfocusedContainerColor = colorResource(id = R.color.gray),
                                        cursorColor = colorResource(id = R.color.light_gray),
                                        focusedTextColor = Color.White,
                                        unfocusedTextColor = Color.White,
                                        focusedContainerColor = colorResource(id = R.color.moon_gray),
                                        disabledLabelColor = colorResource(id = R.color.moon_gray),
                                        focusedIndicatorColor = Color.Transparent,
                                        unfocusedIndicatorColor = Color.Transparent
                                    ),
                                    shape = RoundedCornerShape(8.dp),
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .menuAnchor(MenuAnchorType.PrimaryNotEditable)
                                )

                                ExposedDropdownMenu(expanded = isExpanded,
                                    onDismissRequest = { isExpanded = false },
                                    containerColor = colorResource(id = R.color.gray),
                                    shape = RoundedCornerShape(8.dp),
                                    border = BorderStroke(2.dp,colorResource(id = R.color.moon_gray))) {
                                       DropdownMenuItem(text = { Text("Male",color=Color.White) }, onClick = { gender = "Male"
                                           isExpanded = false })
                                    DropdownMenuItem(text = { Text("Female",color=Color.White) }, onClick = { gender = "Female"
                                        isExpanded = false })
                                }
                            }
                        }
                    }

                    Spacer(modifier = Modifier.size(4.dp))
                    Text(
                        modifier = Modifier.fillMaxWidth(),
                        textAlign = TextAlign.Start, // Aligns text to the left
                        text = registerInfoList[index].message,
                        fontSize = 10.sp,
                        color = Color.White
                    )
                }
            }
            Spacer(modifier = Modifier.height(16.dp))
            Button(modifier = Modifier
                .bounceClickEffect()
                .pointerInteropFilter {
                    when (it.action) {
                        MotionEvent.ACTION_DOWN -> {
                            colorButton = Color.Gray
                        }

                        MotionEvent.ACTION_UP -> {
                            if (isFormValid.value) {
                                // Update page state first
                                scope.launch {
                                    pagerState.animateScrollToPage(pagerState.currentPage + 1)
                                }
                                // Then set color back to white for visual feedback
                                colorButton = Color.White
                            }

                        }
                    }
                    true
                }, colors =
            ButtonDefaults.buttonColors(
                disabledContainerColor = colorResource(id = R.color.gray),
                disabledContentColor = colorResource(id = R.color.black),
                containerColor = colorButton,
                contentColor = colorResource(id = R.color.black)
            ), enabled = isFormValid.value,
                onClick = {
                }) {
                Text(text = "Log in", fontSize = 16.sp)
            }
        }
    }
}

@Composable
fun DatePicker(
    onDateSelected: (Date) -> Unit
) {
    AndroidView(
        modifier = Modifier.fillMaxWidth(),
        factory = { context ->
            val view = LayoutInflater.from(context).inflate(R.layout.date_picker, null)
            val datePicker = view.findViewById<DatePicker>(R.id.datePicker)
            val calendar = Calendar.getInstance() // show today by default
            datePicker.init(
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH)
            ) { _, year, monthOfYear, dayOfMonth ->
                val date = Calendar.getInstance().apply {
                    set(year, monthOfYear, dayOfMonth)
                }.time
                onDateSelected(date)
            }
            datePicker
        }
    )
}

Tried to look for solutions but they weren't successful.

Upvotes: 0

Views: 49

Answers (0)

Related Questions