0

I'm trying to make the following variable, selectedView, mutable so that I can set the current Composable View dynamically.

var selectedView :@Composable () -> Unit =  { testView() }

I'm passing back the Composable function and the following code works, but I can't figure out how to make the variable selectedView updateable. This would work if selectedView variable was mutable.

@Composable
fun testView1() {
    Text("It works! 111")
}

...
    
val navBarItems = listOf(
    NavBarItem("Invite", Icons.Outlined.Send) { testView1() },
    NavBarItem("Messages", Icons.Outlined.Menu) { testView2() },
    NavBarItem("Groups", Icons.Outlined.AccountCircle) { testView3() }
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CurrentView() {
    
    var selectedView :@Composable () -> Unit =  { testView() }

    Scaffold(
        bottomBar = {
            CustomNavBar(navBarItems){
                selectedView  = it
            }
        }
    )
    {
        Box(modifier = Modifier
            .fillMaxSize()
            .padding(it), contentAlignment = Alignment.Center) {
            selectedView?.let { it1 -> it1() }
        }
    }
}

Any assistance would be greatly appreciated.

J. Edgell
  • 1,555
  • 3
  • 16
  • 24

1 Answers1

0

You can use Compose mutable state to hold it. Something like

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
...
var selectedView by remember {
    mutableStateOf<@Composable () -> Unit>({ TestView() })
}

(Note - convention is that @Composable functions are named with UpperCamelCase)

I see what you're trying to do here, but the problem is going to be dealing with configuration changes. Keeping track of that lambda inside CurrentView, it'll get lost and reinitialized on configuration change, such as a screen rotation.

You'd be better served by keeping track of the current screen as a simple value (String, object, enum, etc) as a screen identifier inside a view model (with a saved state handler) or at least in a rememberSaveable.

You could then define either a when on the screen identifier to select which @Composable to call, or put your lambdas inside a map keyed by the screen identifier.

Scott Stanchfield
  • 29,742
  • 9
  • 47
  • 65
  • 1
    Your solution worked for me, thank you! I will look into your other suggestions, I know SwiftUI very well and I'm just starting out with JetPack Compose so I'm sure I'm going down a few wrong rabbit holes in my approach. Thank you for the advice! – J. Edgell Aug 15 '23 at 03:53