为什么第一次单击图标按钮时索引不加一个

Why doesnt the index plus one on the first click of the Iconbutton

所以我做了一个日历。我现在正试图让两个箭头按钮跳过几个月。唯一的问题是,每次我单击图标按钮时,++ 第一次不执行任何操作,但第二次执行某些操作...为什么有人可以帮忙

package com.jens.svensson.jenson_calendar

import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.hilt.navigation.compose.hiltViewModel
import com.jens.svensson.jenson_calendar.data.model.CalendarColors
import com.jens.svensson.jenson_calendar.ui.CalendarViewModel
import com.jens.svensson.jenson_calendar.ui.events.CalendarEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch


@Composable
fun Calendar(
    calendarViewModel: CalendarViewModel = hiltViewModel(),
    isRoundedCorners: Boolean = false,
    startMonth: Int,
    calendarColor: CalendarColors,
    textStyle: TextStyle,
    onDissmissDialog: () -> Unit,
    size: Configuration
){
    val calendarYears = calendarViewModel.calendarYears
    val showMenuState = calendarViewModel.dropDownMenuState.value.showDropDown
    var dropDownPickedState = calendarViewModel.dropDownMenuState.value.pickedItem
    val sizeHeight = size.screenHeightDp
    val sizeWidth = size.screenWidthDp
    val width = sizeWidth * 0.95
    val height = sizeHeight * 0.95
    val coroutineScope = rememberCoroutineScope()



    Dialog(onDismissRequest = onDissmissDialog, properties = DialogProperties(dismissOnClickOutside = true)) {
        Column(modifier = Modifier
            .size(width = width.dp, height = height.dp)
            .padding(15.dp)
            .background(
                calendarColor.calendarColor,
                shape = if (isRoundedCorners) RoundedCornerShape(10) else RectangleShape
            )) {


            Header(isRoundedCorners = isRoundedCorners, color = calendarColor.headerColor)
            Row(
                modifier = Modifier
                    .fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Box(
                    modifier = Modifier
                        .align(Alignment.CenterVertically)
                        .padding(start = 22.dp)
                ) {
                    Row(Modifier.clickable { calendarViewModel.onEvent(CalendarEvent.ShowDropDown(!showMenuState)) }) {
                        Text(
                            text = calendarViewModel.standardMonths[calendarViewModel.dropDownMenuState.value.pickedItem],
                            style = MaterialTheme.typography.h6,
                            color = calendarColor.mainCalendarTextColor
                        )
                        Icon(
                            imageVector = Icons.Default.ArrowDropDown,
                            contentDescription = "Month dropdown arrow",
                            tint = calendarColor.mainCalendarTextColor
                        )
                    }
                    DropdownMenu(
                        expanded = showMenuState,
                        onDismissRequest = { calendarViewModel.onEvent(CalendarEvent.ShowDropDown(!showMenuState)) }) {
                        calendarViewModel.standardMonths.forEachIndexed { index, month ->
                            DropdownMenuItem(onClick = { calendarViewModel.onEvent(CalendarEvent.ClickedMenuItem(index))
                            }) {
                                Row() {
                                    Text(text = month, style = MaterialTheme.typography.h6)
                                }
                            }
                        }
                    }
                }
                IconButton(modifier = Modifier.align(Alignment.CenterVertically), onClick = {}) {
                    Icon(
                        imageVector = Icons.Default.ArrowBack,
                        contentDescription = "Go back one month arrow",
                        tint = calendarColor.mainCalendarTextColor
                    )
                }
                IconButton(modifier = Modifier.align(Alignment.CenterVertically), onClick = {
                    calendarViewModel.onEvent(CalendarEvent.ClickedMenuItem(dropDownPickedState++))
                }) {
                    Icon(
                        imageVector = Icons.Default.ArrowForward,
                        contentDescription = "Go forward one month arrow",
                        tint = calendarColor.mainCalendarTextColor
                    )
                }


            }
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                calendarViewModel.datesList.forEach {
                    Text(text = it, color = calendarColor.mainCalendarTextColor)
                }
            }
            LazyRow(state = calendarViewModel.listState, modifier = Modifier.fillMaxWidth()) {
                calendarYears.forEach {
                    items(it.months.count()) { index ->
                        CalendarRowItem(
                            modifier = Modifier.fillParentMaxWidth(),
                            calendarSize = it.months[index].amountOfDays,
                            initWeekday = it.months[index].startDayOfMonth.ordinal,
                            textColor = MaterialTheme.colors.secondaryVariant,
                            clickedColor = MaterialTheme.colors.primary,
                            textStyle = MaterialTheme.typography.body1
                        )
                    }
                }

            }



            DisposableEffect(Unit) {
                coroutineScope.launch {
                    calendarViewModel.listState.scrollToItem(calendarViewModel.currentMonth)


                }
                onDispose {  }
            }
            
            
            CalendarButtonSection()






        }
    }

}

日历视图模型

package com.jens.svensson.jenson_calendar.ui


import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.jens.svensson.jenson_calendar.data.model.CalendarMonth
import com.jens.svensson.jenson_calendar.data.model.CalendarYear
import com.jens.svensson.jenson_calendar.data.model.YearMonths
import com.jens.svensson.jenson_calendar.domain.repository.CalendarInterface
import com.jens.svensson.jenson_calendar.ui.events.CalendarEvent
import com.jens.svensson.jenson_calendar.ui.state.DropDownMenuState
import dagger.hilt.android.lifecycle.HiltViewModel
import java.time.Month
import java.util.*
import javax.inject.Inject

@HiltViewModel
class CalendarViewModel @Inject constructor(private val repository: CalendarInterface): ViewModel() {
    val datesList: List<String> = repository.getShortenedWeekDays()
    val calendarYears: List<CalendarYear> = repository.createAndReturnYears()
    val standardMonths: List<String> = repository.getStandardMonths()
    val listState = LazyListState()
    val currentMonth: Int = Calendar.getInstance().get(Calendar.MONTH)



    private val _dropdownMenuState = mutableStateOf(DropDownMenuState())
    val dropDownMenuState: State<DropDownMenuState> = _dropdownMenuState

    init {
        _dropdownMenuState.value = dropDownMenuState.value.copy(pickedItem = currentMonth)
    }


    fun onEvent(event: CalendarEvent){
        when(event){
            is CalendarEvent.ShowDropDown -> _dropdownMenuState.value = dropDownMenuState.value.copy(showDropDown =  event.value)
            is CalendarEvent.ClickedMenuItem -> {
                _dropdownMenuState.value = _dropdownMenuState.value.copy(pickedItem = event.value)
            }

        }
    }







    fun getCalendarMonths(yearIndex: Int): List<CalendarMonth>{
        return calendarYears[yearIndex].months
    }
}

新视图模型

package com.jens.svensson.jenson_calendar.ui


import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.jens.svensson.jenson_calendar.data.model.CalendarMonth
import com.jens.svensson.jenson_calendar.data.model.CalendarYear
import com.jens.svensson.jenson_calendar.data.model.YearMonths
import com.jens.svensson.jenson_calendar.domain.repository.CalendarInterface
import com.jens.svensson.jenson_calendar.ui.events.CalendarEvent
import com.jens.svensson.jenson_calendar.ui.state.DropDownMenuState
import dagger.hilt.android.lifecycle.HiltViewModel
import java.time.Month
import java.util.*
import javax.inject.Inject

@HiltViewModel
class CalendarViewModel @Inject constructor(private val repository: CalendarInterface): ViewModel() {
    val datesList: List<String> = repository.getShortenedWeekDays()
    val calendarYears: List<CalendarYear> = repository.createAndReturnYears()
    val standardMonths: List<String> = repository.getStandardMonths()
    val listState = LazyListState()
    val currentMonth: Int = Calendar.getInstance().get(Calendar.MONTH)
    private var datePickedState: Int = 0


    private val _dropdownMenuState = mutableStateOf(DropDownMenuState())
    val dropDownMenuState: State<DropDownMenuState> = _dropdownMenuState

    init {
        _dropdownMenuState.value = dropDownMenuState.value.copy(pickedItem = currentMonth)
    }


    fun onEvent(event: CalendarEvent){
        when(event){
            is CalendarEvent.ShowDropDown -> _dropdownMenuState.value = dropDownMenuState.value.copy(showDropDown =  event.value)
            is CalendarEvent.ClickedMenuItem -> {
                _dropdownMenuState.value = _dropdownMenuState.value.copy(pickedItem = event.value)
            }
            is CalendarEvent.NextMonth -> nextMonth()
            is CalendarEvent.PreviousMonth -> previousMonth()

        }
    }

    fun nextMonth(){
        datePickedState = _dropdownMenuState.value.pickedItem
        if(datePickedState == 11){
            datePickedState = 0
        }else{
            _dropdownMenuState.value = _dropdownMenuState.value.copy(pickedItem = ++datePickedState)
        }


    }
    fun previousMonth(){
        datePickedState = _dropdownMenuState.value.pickedItem
        if(datePickedState == 0){
            datePickedState == 11
        }else{
            _dropdownMenuState.value = dropDownMenuState.value.copy(pickedItem = --datePickedState)
        }


    }





    fun getCalendarMonths(yearIndex: Int): List<CalendarMonth>{
        return calendarYears[yearIndex].months
    }
}

按钮

IconButton(modifier = Modifier.align(Alignment.CenterVertically), onClick = {calendarViewModel.onEvent(CalendarEvent.PreviousMonth)}) {
    Icon(
        imageVector = Icons.Default.ArrowBack,
        contentDescription = "Go back one month arrow",
        tint = calendarColor.mainCalendarTextColor
    )
}
IconButton(modifier = Modifier.align(Alignment.CenterVertically), onClick = {
    calendarViewModel.onEvent(CalendarEvent.NextMonth)
}) {
    Icon(
        imageVector = Icons.Default.ArrowForward,
        contentDescription = "Go forward one month arrow",
        tint = calendarColor.mainCalendarTextColor
    )
}

一个问题是 i++ 在增加之前将当前 i 值传递给计算,因此您将相同的旧值传递给 onEvent。您可以在 this answer 中找到更多详细信息 - 它是关于 C 的,但是 inc/dec 运算符在它们存在的所有语言中都是一样的。您可以使用 ++i,这会在计算中使用它之前增加该值。

但是第二个问题来了。这一行:

var dropDownPickedState = calendarViewModel.dropDownMenuState.value.pickedItem

创建一个局部变量,这些变量不会在重组之间保存。因此,您第一次单击时,会增加局部值,但会将旧值传递给 onEvent,这不会导致重组。

您第二次单击 - 之前增加的值会传递到您的视图模型,这会触发重组并重置您的 dropDownPickedState。

为防止此类错误,请勿在 Compose 视图中使用 var,除非您将其与状态委托一起使用,例如:

var item by viewModel.stateValue  // is ok
var item = viewModel.stateValue.value // is not ok