Search code examples
androidkotlinandroid-jetpack-compose

Jetpack compose date picker


I'm looking for some advice on a Jetpack compose App I'm doing in Android Studio. It is very simple but I'm very new to this. All it does is a calculation on the current date to spit out a number (iPin). This works. It also brings up a date picker so you can do the same calculation on a future or past date. The date picker works and displays the new data (m.Date.Value) via text on the main screen but I can not figure out how to get it to redo the calculation on the number (sPin). I want sPin to update at the same time as mDate.value. Thanks.

@Composable
public fun MyContent(
    imagePainter: Painter,
    modifier: Modifier = Modifier,
){

    // Fetching the Local Context
    val mContext = LocalContext.current

    // Declaring integer values
    // for year, month and day
    val mYear: Int
    val mMonth: Int
    val mDay: Int

    // Initializing a Calendar
    val mCalendar = Calendar.getInstance()

    // Fetching current year, month and day
    mYear = mCalendar.get(Calendar.YEAR)
    mMonth = mCalendar.get(Calendar.MONTH)
    mDay = mCalendar.get(Calendar.DAY_OF_MONTH)

    mCalendar.time = Date()

    var iPin = calcPin(mDay, mMonth, mYear)
    var sPin = 0

    // Declaring a string value to
    // store date in string format
    val mDate = remember { mutableStateOf("") }

    // Declaring DatePickerDialog and setting
    // initial values as current values (present year, month and day)
    val mDatePickerDialog = DatePickerDialog(
        mContext,
        { _: DatePicker, mYear: Int, mMonth: Int, mDayOfMonth: Int ->
            mDate.value = "$mDayOfMonth/${mMonth+1}/$mYear"
            calcPin(mDay, mMonth, mYear).also { sPin = it }
        }, mYear, mMonth, mDay
    )

    Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {

        Image(
            painter = imagePainter,
            contentDescription = null,
            contentScale = ContentScale.Fit,
            modifier = Modifier
                .align(alignment = Alignment.CenterHorizontally)
                .size(250.dp)
        )
        // Displaying the mDate value in the Text
        Text(text = "Todays Number: ${iPin}", fontSize = 30.sp, textAlign = TextAlign.Center)
        // Adding a space of 100dp height
        Spacer(modifier = Modifier.size(100.dp))

        // Creating a button that on
        // click displays/shows the DatePickerDialog
        Button(onClick = {
            mDatePickerDialog.show()
             }, colors = ButtonDefaults.buttonColors(Color(0XFF0F9D58)) ) {
            Text(text = "Select Date", color = Color.White)
        }

        // Adding a space of 50dp height
        Spacer(modifier = Modifier.size(50.dp))

        // Displaying the mDate value in the Text
        Text(text = "Selected Date: ${mDate.value}", fontSize = 30.sp, textAlign = TextAlign.Center)

        Text(text = "Selected Number: ${sPin}", fontSize = 30.sp, textAlign = TextAlign.Center)
        // Adding a space of 100dp height
        Spacer(modifier = Modifier.size(100.dp))
    }
}

fun calcPin(d: Int, m: Int, y: Int): Int {
    var iResult: Int

    iResult = d + m+ y

    return iResult
}

I can not figure out how to get it to redo the calculation (sPin) when the date is selected. I want sPin to update at the same time as mDate.value. I have tried moving the call to the calcPin Function after val mDatePickerDialog I have also moved it to just before Text(text = "Selected Number: ${sPin}", but no luck.


Solution

  • this issue can be fixed by making the varibale sPin a mutable state. Please find the code below.

    var sPin by remember { mutableStateOf(0) }
    

    edit: why? currently, the issue is sPin being just a variable; converting that to a mutable state & wrapping that in a remember block makes the UI to recompose everytime the value of sPin changes.