Error using Material 3 TextField: "None of the following candidates is applicable"


I am making a small program to control some remote devices and I want to take data from a time picker and show it in a text field.

However, Android Studio marks my TextField with this error:

> None of the following candidates is applicable ...

fun EditTextONOFF(context: Context, device_number: Int, on_or_off: String, modifier: Modifier) {

    var hourSet: Int? = 12
    var minuteSet: Int? = 0
    var timeToShow: String = stringResource(R.string.click)
    var selectedTime: TimePickerState? by remember { mutableStateOf(null) }
    var showTimePicker by remember { mutableStateOf(true) }
    val calendar = Calendar.getInstance()
    val hourForPicker: Int = hourSet ?: calendar[Calendar.HOUR_OF_DAY]
    val minuteForPicker: Int = minuteSet ?: calendar[Calendar.MINUTE]
    val device: List<Devices> = devicesDao?.getItem(device_number) as List<Devices>
    val string_onoff: String = stringResource(R.string.ON)


    if (on_or_off == string_onoff) {
        hourSet = device.get(0).hour_on
        minuteSet = device.get(0).minutes_on
        timeToShow = "$hourSet : $minuteSet"
    } else {
        hourSet = device.get(0).hour_off
        minuteSet = device.get(0).minutes_off
        timeToShow = "$hourSet : $minuteSet"
    }

    val timePickerState = rememberTimePickerState(
        initialHour = hourForPicker,
        initialMinute = minuteForPicker,
        is24Hour = true
    )

    Box(propagateMinConstraints = false) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(32.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(24.dp),
        ) {

            Button(
                onClick = { showTimePicker = true }

            ) {
                Text(timeToShow)
            }

            if (showTimePicker) {

                TimePicker(
                    state = timePickerState,
                    Modifier.fillMaxSize()
                )
                Button(

                    onClick = {
                        showTimePicker = false
                        Toast.makeText(context, R.string.setTimeCancel, Toast.LENGTH_SHORT).show()
                    })
                {
                    Text(stringResource(R.string.cancel))
                }

                Button(
                    onClick = {
                        selectedTime = timePickerState
                        showTimePicker = false
                        Toast.makeText(context, R.string.setTimeCancel, Toast.LENGTH_SHORT).show()
                    }) {
                    Text(stringResource(R.string.confirm))

                    if (selectedTime != null) {

                        if (on_or_off == string_onoff) {
                            device.get(0).hour_on = selectedTime!!.hour
                            device.get(0).minutes_on = selectedTime!!.minute
                        } else {
                            device.get(0).hour_off = hourSet
                            device.get(0).minutes_off = minuteSet
                        }
                        timeToShow = "$hourSet : $minuteSet"
                    }
                }
            }
        }
    }
}

https://github.com/DarioLobos/DC-AC-converter-and-control-remote-compose-Android/blob/main/main/java/com/example/dc_acconverterandcontrolremote/DeviceScheduler.kt

1
Feb 14 at 8:45 PM
User AvatarDario Lobos
#android#android-jetpack-compose#material3

Accepted Answer

The immediate problem is that you call TextField with parameters that do not exist:

  • colors is expected to be of type TextFieldColors (which is a container for multiple colors), but you provide a Color (which is only a single color)
  • The parameter Value begins with a lower case v: value = ...
  • label takes a composable function as its value, not the return value of a composable function. You must therefore wrap the value in curly braces: label = { Text(on_or_off) }
  • lineLimits only exists for the TextField overload that is based on a TextFieldState. When using a String value (like you do), though, you have to use the parameter singleLine = true instead.
  • placeholder takes a composable function as its value, not the return value of a composable function. You must therefore wrap the value in curly braces: placeholder = { Text(stringResource(R.string.click)) }
  • The parameter Modifier begins with a lower case m: modifier = ...
  • You are missing the required parameter onValueChange which takes a lambda that is executed every time the user changes the content of the TextField.

Everything put together your TextField should look like this (set the colors to the TextFieldColors you require):

TextField(
    // colors = MaterialTheme.colorScheme.onPrimary,
    readOnly = false,
    enabled = false,
    value = timeToShow,
    onValueChange = { /* ... */ },
    label = { Text(on_or_off) },
    singleLine = true,
    placeholder = { Text(stringResource(R.string.click)) },
    modifier = Modifier.clickable {
        // ...
    },
)

Although this fixes the error you observed, your code still won't work as expected. For starters, the TimePickerDialog object is never used anywhere. It is unclear why you even want to use the android.app.TimePickerDialog from the view system when you use Compose. Mixing these is usually not a good idea. There is a TimePicker composable that you could use instead (currently in alpha, so you would need to use the alpha Compose BOM), or you could simply write your own. Furthermore, timeToShow needs to be wrapped in a MutableState, otherwise Compose won't update the UI when that variable changes. And finally, it looks like you want to use the TextField to only display a value. If you don't want the user to interact with the text then you should consider using a simple Text composable, not a TextField.


I also glanced at the rest of your code from the GitHub repository you linked. There are a lot of rather severe issues in there (like the defunct Room setup, missing/wrong coroutine handling and the leaking Context). Some of it doesn't even look salvageable. You might want to go back to the drawing board and start from scratch.

Some pointers:

  • Use a layered architecture with view models.

  • Work through the Room code labs Persist data with Room and Read and update data with Room to learn how Room should be properly used with coroutines. Make sure all your DAO functions either return a Flow or are suspending - it must be exactly one of the two.

  • For the UI, only use Material 3 Compose components, no View components like the android.app.TimePickerDialog.

  • Don't use the obsolete and buggy java.util.Calendar class, use the classes from the java.time package if you insist on using Java. Better yet, though: Kotlin has native support for Clock and Instant, and the official kotlinx-datetime library provides LocalDate and LocalDateTime, among others.

  • Never pass Context to a composable. If you need a Context, use LocalContext.current.

User Avatartyg
Feb 15 at 12:37 AM
1