0

I'm creating a date-of-birth picker screen with Jetpack Compose in Kotlin, where I need to let users select a date using a DatePickerDialog. I'm invoking this Composable function within onCreate() using setContent {. }. The UI displays a rectangular OutlinedTextField with the placeholder "Tap to select DOB", but when I click on it, nothing appears — the date picker dialog isn't shown.

Therefore, no date is picked, and the "Next" button is greyed out (disabled) because it's dependent on a non-empty DOB field.

I've checked that the clickable modifier is being applied, and I've also put the dialog within remember {. }. Nevertheless, the dialog never opens when clicking the field.

My objective is to enable users to select a valid birth date from a calendar dialog, and when selected, allow the "Next" button to advance.

Can anyone provide some insight into why the DatePickerDialog isn't displaying, and how one should actually trigger it in a Jetpack Compose environment?

@Composable fun ChooseDob( onDobSelected: (String) -> Unit ) { val context = LocalContext.current var dob by remember { mutableStateOf("") } val calendar = Calendar.getInstance() Column( modifier = Modifier .fillMaxSize() .padding(32.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Select your Date of Birth", style = MaterialTheme.typography.headlineMedium, color = Color.Black, fontSize = 24.sp, fontWeight = FontWeight.Bold, modifier = Modifier.align(Alignment.Start) ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( value = dob, onValueChange = {}, modifier = Modifier .fillMaxWidth() .clickable { val datePickerDialog = DatePickerDialog( context, { _, year, month, dayOfMonth -> val selectedCalendar = Calendar.getInstance().apply { set(Calendar.YEAR, year) set(Calendar.MONTH, month) set(Calendar.DAY_OF_MONTH, dayOfMonth) } val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.US) dob = formatter. Format(selectedCalendar.time) }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) ).apply { datePicker.maxDate = System.currentTimeMillis() } datePickerDialog.show() }, readOnly = true, placeholder = { Text("Tap to select DOB") } ) Spacer(modifier = Modifier.height(16.dp)) Button( onClick = { onDobSelected(dob) }, enabled = dob.isNotBlank(), modifier = Modifier.align(Alignment.End), colors = ButtonDefaults.buttonColors( containerColor = if (dob.isNotBlank()) Color(0xFF2196F3) else Color.Gray ) ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "Next", tint = Color.White ) } } } } 
1
  • 3
    You appear to be trying to use the DatePickerDialog class. For Compose, use the DatePickerDialog() composable function. You will need to update state from your clickable() and conditionally render the dialog based upon that state. Commented May 4 at 21:16

2 Answers 2

1

The OutlinedTextField has its own internal focus handling, and using clickable on it can sometimes interfere with its behavior. Instead, you should wrap the OutlinedTextField in a Box or another container and apply the clickable modifier to that container.

@Composable fun ChooseDob( onDobSelected: (String) -> Unit ) { val context = LocalContext.current var dob by remember { mutableStateOf("") } val calendar = Calendar.getInstance() Column( modifier = Modifier .fillMaxSize() .padding(32.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Select your Date of Birth", style = MaterialTheme.typography.headlineMedium, color = Color.Black, fontSize = 24.sp, fontWeight = FontWeight.Bold, modifier = Modifier.align(Alignment.Start) ) Spacer(modifier = Modifier.height(16.dp)) Box( modifier = Modifier .fillMaxWidth() .clickable { val datePickerDialog = DatePickerDialog( context, { _, year, month, dayOfMonth -> val selectedCalendar = Calendar.getInstance().apply { set(Calendar.YEAR, year) set(Calendar.MONTH, month) set(Calendar.DAY_OF_MONTH, dayOfMonth) } val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.US) dob = formatter.format(selectedCalendar.time) }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) ).apply { datePicker.maxDate = System.currentTimeMillis() } datePickerDialog.show() } ) { OutlinedTextField( value = dob, onValueChange = {}, modifier = Modifier.fillMaxWidth(), readOnly = true, placeholder = { Text("Tap to select DOB") } ) } Spacer(modifier = Modifier.height(16.dp)) Button( onClick = { onDobSelected(dob) }, enabled = dob.isNotBlank(), modifier = Modifier.align(Alignment.End), colors = ButtonDefaults.buttonColors( containerColor = if (dob.isNotBlank()) Color(0xFF2196F3) else Color.Gray ) ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "Next", tint = Color.White ) } } } } 
Sign up to request clarification or add additional context in comments.

Comments

1

The main issue in your code is that you're trying to show the DatePickerDialog directly from a click handler, which isn't the recommended approach in Jetpack Compose.
Here's the corrected version of your composable:

@Composable fun ChooseDob( onDobSelected: (String) -> Unit ) { val context = LocalContext.current var dob by remember { mutableStateOf("") } var showDatePicker by remember { mutableStateOf(false) } // State to control dialog visibility val calendar = Calendar.getInstance() Column( modifier = Modifier .fillMaxSize() .padding(32.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Select your Date of Birth", style = MaterialTheme.typography.headlineMedium, color = Color.Black, fontSize = 24.sp, fontWeight = FontWeight.Bold, modifier = Modifier.align(Alignment.Start) ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( value = dob, onValueChange = {}, modifier = Modifier .fillMaxWidth() .clickable { showDatePicker = true }, readOnly = true, placeholder = { Text("Tap to select DOB") } ) Spacer(modifier = Modifier.height(16.dp)) Button( onClick = { onDobSelected(dob) }, enabled = dob.isNotBlank(), modifier = Modifier.align(Alignment.End), colors = ButtonDefaults.buttonColors( containerColor = if (dob.isNotBlank()) Color(0xFF2196F3) else Color.Gray ) ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "Next", tint = Color.White ) } } } // Date picker dialog if (showDatePicker) { DatePickerDialog( onDismissRequest = { showDatePicker = false }, confirmButton = { TextButton( onClick = { showDatePicker = false } ) { Text("OK") } }, dismissButton = { TextButton( onClick = { showDatePicker = false } ) { Text("Cancel") } } ) { AndroidDatePicker( modifier = Modifier.wrapContentSize(), year = calendar.get(Calendar.YEAR), month = calendar.get(Calendar.MONTH), dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH), onDateChanged = { year, month, day -> val selectedCalendar = Calendar.getInstance().apply { set(Calendar.YEAR, year) set(Calendar.MONTH, month) set(Calendar.DAY_OF_MONTH, day) } val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.US) dob = formatter.format(selectedCalendar.time) } ) } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.