Reputation: 159
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