Skip to content

Instantly share code, notes, and snippets.

@hlnstepanova
Created December 14, 2020 18:48
Show Gist options
  • Save hlnstepanova/759722efad9cd7edddc87da27c1fabc4 to your computer and use it in GitHub Desktop.
Save hlnstepanova/759722efad9cd7edddc87da27c1fabc4 to your computer and use it in GitHub Desktop.
MainActivity.kt
package de.comp.proj.androidApp
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.widget.Toolbar
import androidx.core.view.GravityCompat
import androidx.databinding.DataBindingUtil
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.navigateUp
import com.google.android.material.navigation.NavigationView
import de.comp.proj.androidApp.databinding.ActivityMainBinding
import de.comp.proj.androidApp.databinding.NavHeaderBinding
import de.comp.proj.androidApp.fragments.login.LoginFragmentDirections
import de.comp.proj.androidApp.fragments.login.LoginViewModel
import de.comp.proj.shared.models.LoginModel
import dev.icerock.moko.mvvm.MvvmEventsActivity
import dev.icerock.moko.mvvm.createViewModelFactory
import dev.icerock.moko.mvvm.dispatcher.eventsDispatcherOnMain
import dev.icerock.moko.resources.desc.StringDesc
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
class MainActivity :
MvvmEventsActivity<ActivityMainBinding, LoginModel, LoginModel.EventsListener>(),
NavigationView.OnNavigationItemSelectedListener {
private val mainScope = MainScope()
override val layoutId: Int = R.layout.activity_main
override val viewModelVariableId: Int = BR.viewModel
override val viewModelClass: Class<LoginModel> =
LoginModel::class.java
val drawerLayout by lazy { findViewById<DrawerLayout>(R.id.drawerLayout) }
val navController by lazy {
(supportFragmentManager.findFragmentById(R.id.navHostFragment) as NavHostFragment).navController
}
val navigationView by lazy { findViewById<NavigationView>(R.id.navView) }
private var loginModel: LoginModel? = null
private lateinit var headerBinding: NavHeaderBinding
private val appBarConfiguration by lazy {
AppBarConfiguration(
setOf(
R.id.loginFragment,
R.id.deviceListFragment,
R.id.favouriteListFragment,
R.id.imprintFragment
), drawerLayout
)
}
override fun viewModelFactory(): ViewModelProvider.Factory {
return createViewModelFactory {
LoginModel(
eventsDispatcher = eventsDispatcherOnMain()
)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupDataBinding()
setupNavigation()
setupViewModel()
hideLoggedNavItems()
loginModel!!.logged.addObserver { logged ->
logged.let {
if (!logged) {
navController.popBackStack(R.id.loginFragment, false)
}
//if user logged in show relevant menu items
val menu = navigationView.menu
menu.findItem(R.id.loginFragment).isVisible = !logged
menu.findItem(R.id.logout).isVisible = logged
menu.findItem(R.id.accountFragment).isVisible = logged
//invalidate header
updateNavHeader()
}
}
}
private fun setupDataBinding() {
headerBinding = DataBindingUtil.inflate(
layoutInflater, R.layout.nav_header, binding.navView, false
)
binding.navView.addHeaderView(headerBinding.root)
}
private fun setupNavigation() {
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val toggle = ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
// Show and Manage the Drawer and Back Icon
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
NavigationUI.setupWithNavController(toolbar, navController, drawerLayout)
NavigationUI.setupWithNavController(navigationView, navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.id == R.id.loginFragment) {
loginModel?.onLogout()
}
}
navigationView.setNavigationItemSelectedListener(this)
navigationView.bringToFront()
drawerLayout.isEnabled = true
}
//refresh navigation header after login or logout
private fun updateNavHeader() {
headerBinding.invalidateAll()
}
private fun setupViewModel() {
try {
val viewModelProvider = ViewModelProvider(
navController.getViewModelStoreOwner(R.id.nav_graph),
viewModelFactory()
)
loginModel = viewModelProvider.get(LoginModel::class.java)
headerBinding.viewModel = loginModel
} catch (e: IllegalArgumentException) {
e.printStackTrace()
}
}
private fun hideLoggedNavItems() {
val menu = navigationView.menu
menu.findItem(R.id.logout).isVisible = false
menu.findItem(R.id.accountFragment).isVisible = false
menu.findItem(R.id.loginFragment).isVisible = true
}
override fun onSupportNavigateUp(): Boolean {
// Allows NavigationUI to support proper up navigation or the drawer layout
// drawer menu, depending on the situation
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
return NavigationUI.onNavDestinationSelected(
item!!,
navController
) || super.onOptionsItemSelected(item)
}
fun onLoggedChange(logged: Boolean) {
if (logged) {
navController.popBackStack(R.id.loginFragment, false)
}
refreshMenuItems(logged)
}
fun refreshMenuItems(logged: Boolean) {
//if user logged in show relevant menu items
val menu = navigationView.menu
menu.findItem(R.id.loginFragment).isVisible = !logged
menu.findItem(R.id.logout).isVisible = logged
menu.findItem(R.id.accountFragment).isVisible = logged
//invalidate header
updateNavHeader()
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.logout -> {
loginModel?.onLogout()
}
}
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
override fun onDestroy() {
super.onDestroy()
mainScope.cancel()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment