How to clear previously selected items in Navigation Drawer (Jetpack Compose)

61 Views Asked by At

I have navigation drawer with multiple menu Items. When I click on any item it gets selected (Inbox) with highlighted color . After that if I click some other items (flagged Mail) it also gets selected with highlighted color . But previous selected (Inbox) should be cleared (highlighted color should be gone).

Only one item should be shown as Highlighted at a time . In my case both items are being highlighted as selected .ScreenShot

@Composable
fun DrawerItem(
  folderItem: NewFolderTableData,
  index: Int,
  navigationState: DrawerState,
  submenuList: ImmutableList<NewFolderTableData> = 
  emptyList<NewFolderTableData>().toImmutableList(),
  onMenuClick: (String)->Unit
) {

  val scope = rememberCoroutineScope()
  var selectedItemIndex by rememberSaveable {
    mutableStateOf("")
  }

  var showMoreSubMenu by rememberSaveable {
    mutableStateOf(false)
  }

  var showInboxSubMenu by rememberSaveable {
    mutableStateOf(false)
  }

  val title = if (folderItem.foldername == Const.MailFolder.TYPE_FOLDER_MAIL_SHOW_MORE) {
    if (!showMoreSubMenu) {
        Const.MailFolder.TYPE_FOLDER_MAIL_SHOW_MORE
    } else {
        Const.MailFolder.TYPE_FOLDER_MAIL_HIDE_MORE
    }
  } else {
    folderItem.foldername
  }

  NavigationDrawerItem(label = {
    Text(text = title)
  }, selected = title == selectedItemIndex, onClick = {
    onMenuClick(folderItem.foldername)
    if (folderItem.foldername == Const.MailFolder.TYPE_FOLDER_MAIL_SHOW_MORE) {
        showMoreSubMenu = !showMoreSubMenu
    } else {
        selectedItemIndex = title
        scope.launch {
            navigationState.close()
        }
    }
  }, icon = {
    val iconId = getFolderIcons(folderItem.foldername)
    if (iconId != -1) {
        Image(
            painterResource(id = iconId),
            contentDescription = folderItem.foldername
        )
    }
}, badge = {
    if (folderItem.foldername.equals(
            Const.MailFolder.TYPE_FOLDER_MAIL_SHOW_MORE,
            ignoreCase = true
        )
    ) {
        if (!showMoreSubMenu) {
            SetRightIcon(vector = Icons.Outlined.KeyboardArrowDown, foldername = folderItem.foldername){
            }
        } else {
            SetRightIcon(vector = Icons.Outlined.KeyboardArrowUp, foldername = folderItem.foldername){
            }
        }
    } else if (folderItem.foldername.equals(
            Const.MailFolder.TYPE_FOLDER_MAIL_INBOX,
            ignoreCase = true
        ) && submenuList.isNotEmpty()
    ) {
        if(!showInboxSubMenu){
            SetRightIcon(vector = Icons.Outlined.KeyboardArrowDown, foldername = folderItem.foldername){
                showInboxSubMenu = !showInboxSubMenu
            }
        }else{
            SetRightIcon(vector = Icons.Outlined.KeyboardArrowUp, foldername = folderItem.foldername){
                showInboxSubMenu = !showInboxSubMenu
            }
        }

    } else if (folderItem.foldername.equals(
            Const.MailFolder.TYPE_FOLDER_MAIL_TRASH,
            ignoreCase = true
        ) || folderItem.foldername.equals(
            Const.MailFolder.TYPE_FOLDER_MAIL_JUNK, ignoreCase = true
        )
    ) {
        SetRightIcon(vector = Icons.Filled.Delete, foldername = folderItem.foldername){
        }
    }else if(folderItem.foldername.equals(Const.MailFolder.TYPE_FOLDER_MAIL_ADD, ignoreCase = true)){
        SetRightIcon(vector = Icons.Filled.Add, foldername = folderItem.foldername){
            
        }
    }

  }, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)


  )

  AnimatedVisibility(visible = showMoreSubMenu || showInboxSubMenu) {
    DrawSubMenu(subList = submenuList, navigationState)
  } 
}
2

There are 2 best solutions below

0
BenjyTec On BEST ANSWER

The way you implemented it now, each DrawerItem has its own selectedItemIndex. Once you click the item, it will be highlighted. However, clicking one DrawerItem does not affect the local selectedItemIndex of all other DrawerItems.

So you will have to move the selection logic into the parent Composable. When you click a DrawerItem, update the selected index in the parent Composable.
You have not provided any code, but I will provide a generic example:

// move this declaration from DrawerItem into here
var selectedItemIndex by rememberSaveable {
    mutableStateOf("")
}

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("My Drawer", modifier = Modifier.padding(16.dp))
            Divider()
            DrawerItem(
                selectedItemIndex = selectedItemIndex,
                updateSelectedItemIndex = { newItemIndex ->
                    selectedItemIndex = newItemIndex
                },
                //... other parameters
            )
            // ...other DrawerItem Composables
        }
    }
) {
    // Screen content
}

Now, update the signature of your DrawerItem Composable as follows:

@Composable
fun DrawerItem(
  selectedItemIndex: String,
  updateSelectedItemIndex: (String) -> Unit,
  // ... other parameters
) {

    //..
    onClick = {
        onMenuClick(folderItem.foldername)
        if (folderItem.foldername == Const.MailFolder.TYPE_FOLDER_MAIL_SHOW_MORE) {
            showMoreSubMenu = !showMoreSubMenu
        } else {
            updateSelectedItemIndex(title)  // invoke callback function to update selection in parent
            scope.launch {
                navigationState.close()
            }
        }
    },
    //...
}
0
Leviathan On

Currently each DrawerItem has its own selectedItemIndex that can be set to true. You should hoist that state out to ModalDrawerSheet so it only exists once.