Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigate using View Model in Jetpack Compose

Here is my MainActivity.kt file

Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    NavigationHoster()
                }

here is navhoster function

@Composable
fun NavigationHoster(){
    val navController = rememberNavController();
    
    NavHost(navController = navController, startDestination = "Home"){
        composable("Home"){ HomeScreen(navController = navController)}
        composable("Chat"){ ChatScreen()}
    }
}

here is HomeScreen Function

@OptIn(ExperimentalMaterial3Api::class)
//@Preview(showBackground = true, showSystemUi = true)
@Composable
fun HomeScreen(
    homeViewModel: HomeViewModel = viewModel(),
    navController: NavController
){
    val HomeViewState by homeViewModel.uiState.collectAsState()
    Scaffold (
        topBar = {
            TopAppBar(title = {
                Text(text = "Chat Wallet", style = MaterialTheme.typography.titleMedium)
            }, colors = TopAppBarDefaults.mediumTopAppBarColors(
                containerColor = MaterialTheme.colorScheme.primary,
                titleContentColor = MaterialTheme.colorScheme.background
            ))
        }
    ){
        paddingValues -> Box(modifier = Modifier.padding(paddingValues).fillMaxSize(), contentAlignment = Alignment.Center) {
            IconButton(onClick = { navController.navigate("Chat") }, colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.primary)) {
                Icon(painter = painterResource(id = R.drawable.baseline_chat_24), contentDescription = null, tint = MaterialTheme.colorScheme.background)
            }

        }
    }
}

Here is my ViewModel

class HomeViewModel : ViewModel(){
    private var _uiState = MutableStateFlow(HomeData())
    var uiState : StateFlow<HomeData> = _uiState.asStateFlow()

    public fun ChangeName() {
        _uiState.value = HomeData(UserName = "hello there")
    }
}

These codes are works well and I tested. this viewmodel and screen file may be not linked.because I does different tests by changing it. can I know how to navigate to chat screen by calling changeName function from ui? I have no idea how to implement it

I didn't get any way to import navcontroller to viewmodel. so I stucked with that point. I thaught it have to import to viewmodel.

please give me simple example as well. thank you.

like image 659
Gayantha Avatar asked Oct 25 '25 16:10

Gayantha


1 Answers

You best approach would be to add a variable to the viewModel called navigateToChatScreen and then when this variable is true you can navigate in your composable like this:

    class HomeViewModel : ViewModel(){
    private var _uiState = MutableStateFlow(HomeData())
    var uiState : StateFlow<HomeData> = _uiState.asStateFlow()

private var _navigateToChatScreen = MutableStateFlow(false)
    var navigateToChatScreen : StateFlow<Boolean> = _navigateToChatScreen.asStateFlow()

    public fun ChangeName() {
        _uiState.value = HomeData(UserName = "hello there")
        _navigateToChatScreen.value = true
    }
}

Then you do it like this in your composable:

    @Composable
fun HomeScreen(
    homeViewModel: HomeViewModel = viewModel(),
    navController: NavController
){
    val HomeViewState by homeViewModel.uiState.collectAsState()

    val navigateToChatScreen by homeViewModel.navigateToChatScreen.collectAsState()

Launchedeffect(key= navigateToChatScreen){
  If(navigateToChatScreen){
     navController.navigate("chat")
  }
}
    Scaffold (
        topBar = {
            TopAppBar(title = {
                Text(text = "Chat Wallet", style = MaterialTheme.typography.titleMedium)
            }, colors = TopAppBarDefaults.mediumTopAppBarColors(
                containerColor = MaterialTheme.colorScheme.primary,
                titleContentColor = MaterialTheme.colorScheme.background
            ))
        }
    ){
        paddingValues -> Box(modifier = Modifier.padding(paddingValues).fillMaxSize(), contentAlignment = Alignment.Center) {
            IconButton(onClick = { homeViewModel.changeName()}, colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.primary)) {
                Icon(painter = painterResource(id = R.drawable.baseline_chat_24), contentDescription = null, tint = MaterialTheme.colorScheme.background)
            }

        }
    }
}
like image 53
Ayman Ait Avatar answered Oct 27 '25 06:10

Ayman Ait



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!