@@ -20,25 +20,19 @@ import android.app.Activity
20
20
import android.content.Intent
21
21
import android.net.ConnectivityManager
22
22
import android.os.Bundle
23
- import android.view.View
24
- import android.widget.FrameLayout
23
+ import android.view.Menu
25
24
import androidx.activity.viewModels
26
25
import androidx.appcompat.app.AppCompatActivity
27
26
import androidx.appcompat.widget.Toolbar
28
- import androidx.core.view.GravityCompat
29
- import androidx.core.view.updatePadding
30
- import androidx.drawerlayout.widget.DrawerLayout
31
27
import androidx.lifecycle.Observer
32
28
import androidx.navigation.NavController
33
29
import androidx.navigation.fragment.NavHostFragment
34
30
import androidx.navigation.ui.AppBarConfiguration
35
31
import androidx.navigation.ui.setupWithNavController
36
- import androidx.recyclerview.widget.RecyclerView
37
32
import com.firebase.ui.auth.IdpResponse
38
- import com.google.android.material.navigation.NavigationView
39
33
import com.google.samples.apps.iosched.R
40
34
import com.google.samples.apps.iosched.ar.ArActivity
41
- import com.google.samples.apps.iosched.databinding.NavigationHeaderBinding
35
+ import com.google.samples.apps.iosched.databinding.ActivityMainBinding
42
36
import com.google.samples.apps.iosched.shared.analytics.AnalyticsActions
43
37
import com.google.samples.apps.iosched.shared.analytics.AnalyticsHelper
44
38
import com.google.samples.apps.iosched.shared.di.CodelabsEnabledFlag
@@ -50,14 +44,8 @@ import com.google.samples.apps.iosched.ui.messages.SnackbarMessageManager
50
44
import com.google.samples.apps.iosched.ui.signin.SignInDialogFragment
51
45
import com.google.samples.apps.iosched.ui.signin.SignOutDialogFragment
52
46
import com.google.samples.apps.iosched.util.HeightTopWindowInsetsListener
53
- import com.google.samples.apps.iosched.util.NoopWindowInsetsListener
54
- import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
55
- import com.google.samples.apps.iosched.util.navigationItemBackground
56
- import com.google.samples.apps.iosched.util.shouldCloseDrawerFromBackPress
57
47
import com.google.samples.apps.iosched.util.signin.FirebaseAuthErrorCodeConverter
58
48
import com.google.samples.apps.iosched.util.updateForTheme
59
- import com.google.samples.apps.iosched.widget.HashtagIoDecoration
60
- import com.google.samples.apps.iosched.widget.NavigationBarContentFrameLayout
61
49
import dagger.hilt.android.AndroidEntryPoint
62
50
import timber.log.Timber
63
51
import java.util.UUID
@@ -112,15 +100,10 @@ class MainActivity : AppCompatActivity(), NavigationHost {
112
100
113
101
private val viewModel: MainActivityViewModel by viewModels()
114
102
115
- private lateinit var content: FrameLayout
116
- private lateinit var drawer: DrawerLayout
117
- private lateinit var navigation: NavigationView
118
- private lateinit var navHeaderBinding: NavigationHeaderBinding
103
+ private lateinit var binding: ActivityMainBinding
104
+
119
105
private lateinit var navController: NavController
120
106
private lateinit var navHostFragment: NavHostFragment
121
-
122
- private lateinit var statusScrim: View
123
-
124
107
private var currentNavId = NAV_ID_NONE
125
108
126
109
// For sending pinned sessions as JSON to the AR module
@@ -133,111 +116,36 @@ class MainActivity : AppCompatActivity(), NavigationHost {
133
116
// Update for Dark Mode straight away
134
117
updateForTheme(viewModel.currentTheme)
135
118
136
- setContentView(R .layout.activity_main)
137
-
138
- val drawerContainer: NavigationBarContentFrameLayout = findViewById(R .id.drawer_container)
139
- // Let's consume any
140
- drawerContainer.setOnApplyWindowInsetsListener { v, insets ->
141
- // Let the view draw it's navigation bar divider
142
- v.onApplyWindowInsets(insets)
143
-
144
- // Consume any horizontal insets and pad all content in. There's not much we can do
145
- // with horizontal insets
146
- v.updatePadding(
147
- left = insets.systemWindowInsetLeft,
148
- right = insets.systemWindowInsetRight
149
- )
150
- insets.replaceSystemWindowInsets(
151
- 0 , insets.systemWindowInsetTop,
152
- 0 , insets.systemWindowInsetBottom
153
- )
154
- }
155
-
156
- content = findViewById(R .id.content_container)
157
- content.systemUiVisibility = View .SYSTEM_UI_FLAG_LAYOUT_STABLE or
158
- View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
159
- View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
160
- // Make the content ViewGroup ignore insets so that it does not use the default padding
161
- content.setOnApplyWindowInsetsListener(NoopWindowInsetsListener )
162
-
163
- statusScrim = findViewById(R .id.status_bar_scrim)
164
- statusScrim.setOnApplyWindowInsetsListener(HeightTopWindowInsetsListener )
119
+ binding = ActivityMainBinding .inflate(layoutInflater)
120
+ setContentView(binding.root)
165
121
166
- drawer = findViewById(R .id.drawer)
167
-
168
- navHeaderBinding = NavigationHeaderBinding .inflate(layoutInflater).apply {
169
- lifecycleOwner = this @MainActivity
170
- }
122
+ binding.statusBarScrim.setOnApplyWindowInsetsListener(HeightTopWindowInsetsListener )
171
123
172
124
navHostFragment = supportFragmentManager
173
125
.findFragmentById(R .id.nav_host_fragment) as NavHostFragment
174
126
175
127
navController = navHostFragment.navController
176
128
navController.addOnDestinationChangedListener { _, destination, _ ->
177
129
currentNavId = destination.id
178
- val isTopLevelDestination = TOP_LEVEL_DESTINATIONS .contains(destination.id)
179
- val lockMode = if (isTopLevelDestination) {
180
- DrawerLayout .LOCK_MODE_UNLOCKED
181
- } else {
182
- DrawerLayout .LOCK_MODE_LOCKED_CLOSED
183
- }
184
- drawer.setDrawerLockMode(lockMode)
130
+ // TODO: hide nav if not a top-level destination?
185
131
}
186
132
187
- navigation = findViewById(R .id.navigation)
188
- navigation.apply {
189
- // Add the #io19 decoration
190
- val menuView = findViewById<RecyclerView >(R .id.design_navigation_view)?.apply {
191
- addItemDecoration(HashtagIoDecoration (context))
192
- }
193
- // Update the Navigation header view to pad itself down
194
- navHeaderBinding.root.doOnApplyWindowInsets { v, insets, padding ->
195
- v.updatePadding(top = padding.top + insets.systemWindowInsetTop)
196
- // NavigationView doesn't dispatch insets to the menu view, so pad the bottom here.
197
- menuView?.updatePadding(bottom = insets.systemWindowInsetBottom)
198
- }
199
- addHeaderView(navHeaderBinding.root)
200
-
201
- itemBackground = navigationItemBackground(context)
202
-
203
- menu.findItem(R .id.navigation_map).isVisible = mapFeatureEnabled
204
- menu.findItem(R .id.navigation_codelabs).isVisible = codelabsFeatureEnabled
205
- menu.findItem(R .id.navigation_explore_ar).apply {
206
- // Handle launching new activities, otherwise assume the destination is handled
207
- // by the nav graph. We want to launch a new Activity for only the AR menu
208
- isVisible = exploreArFeatureEnabled
209
- setOnMenuItemClickListener {
210
- if (connectivityManager.activeNetworkInfo?.isConnected == true ) {
211
- if (viewModel.arCoreAvailability.value?.isSupported == true ) {
212
- analyticsHelper
213
- .logUiEvent(
214
- " Navigate to Explore I/O ARCore supported" ,
215
- AnalyticsActions .CLICK
216
- )
217
- openExploreAr()
218
- } else {
219
- analyticsHelper
220
- .logUiEvent(
221
- " Navigate to Explore I/O ARCore NOT supported" ,
222
- AnalyticsActions .CLICK
223
- )
224
- openArCoreNotSupported()
225
- }
226
- } else {
227
- openNoConnection()
228
- }
229
- closeDrawer()
230
- true
231
- }
232
- }
133
+ // Either of two different navigation views might exist depending on the configuration.
134
+ binding.bottomNavigation?.apply {
135
+ configureNavMenu(menu)
233
136
setupWithNavController(navController)
137
+ setOnItemReselectedListener { } // prevent navigating to the same item
138
+ }
139
+ binding.navigationRail?.apply {
140
+ configureNavMenu(menu)
141
+ setupWithNavController(navController)
142
+ setOnItemReselectedListener { } // prevent navigating to the same item
234
143
}
235
144
236
145
if (savedInstanceState == null ) {
237
- // default to showing Home
238
- val initialNavId = intent.getIntExtra(EXTRA_NAVIGATION_ID , R .id.navigation_feed)
239
- navigation.setCheckedItem(initialNavId) // doesn't trigger listener
240
- navigateTo(initialNavId)
146
+ currentNavId = navController.graph.startDestination
147
+ val requestedNavId = intent.getIntExtra(EXTRA_NAVIGATION_ID , currentNavId)
148
+ navigateTo(requestedNavId)
241
149
}
242
150
243
151
viewModel.theme.observe(this , Observer (::updateForTheme))
@@ -278,14 +186,44 @@ class MainActivity : AppCompatActivity(), NavigationHost {
278
186
)
279
187
}
280
188
189
+ private fun configureNavMenu (menu : Menu ) {
190
+ menu.findItem(R .id.navigation_map)?.isVisible = mapFeatureEnabled
191
+ menu.findItem(R .id.navigation_codelabs)?.isVisible = codelabsFeatureEnabled
192
+ menu.findItem(R .id.navigation_explore_ar)?.apply {
193
+ // Handle launching new activities, otherwise assume the destination is handled
194
+ // by the nav graph. We want to launch a new Activity for only the AR menu item.
195
+ isVisible = exploreArFeatureEnabled
196
+ setOnMenuItemClickListener {
197
+ if (connectivityManager.activeNetworkInfo?.isConnected == true ) {
198
+ if (viewModel.arCoreAvailability.value?.isSupported == true ) {
199
+ analyticsHelper.logUiEvent(
200
+ " Navigate to Explore I/O ARCore supported" ,
201
+ AnalyticsActions .CLICK
202
+ )
203
+ openExploreAr()
204
+ } else {
205
+ analyticsHelper.logUiEvent(
206
+ " Navigate to Explore I/O ARCore NOT supported" ,
207
+ AnalyticsActions .CLICK
208
+ )
209
+ openArCoreNotSupported()
210
+ }
211
+ } else {
212
+ openNoConnection()
213
+ }
214
+ true
215
+ }
216
+ }
217
+ }
218
+
281
219
override fun registerToolbarWithNavigation (toolbar : Toolbar ) {
282
- val appBarConfiguration = AppBarConfiguration (TOP_LEVEL_DESTINATIONS , drawer )
220
+ val appBarConfiguration = AppBarConfiguration (TOP_LEVEL_DESTINATIONS )
283
221
toolbar.setupWithNavController(navController, appBarConfiguration)
284
222
}
285
223
286
224
override fun onRestoreInstanceState (savedInstanceState : Bundle ) {
287
225
super .onRestoreInstanceState(savedInstanceState)
288
- currentNavId = navigation.checkedItem?.itemId ? : NAV_ID_NONE
226
+ currentNavId = navController.currentDestination?.id ? : NAV_ID_NONE
289
227
}
290
228
291
229
override fun onActivityResult (requestCode : Int , resultCode : Int , data : Intent ? ) {
@@ -304,32 +242,15 @@ class MainActivity : AppCompatActivity(), NavigationHost {
304
242
}
305
243
}
306
244
307
- override fun onBackPressed () {
308
- /* *
309
- * If the drawer is open, the behavior changes based on the API level.
310
- * When gesture nav is enabled (Q+), we want back to exit when the drawer is open.
311
- * When button navigation is enabled (on Q or pre-Q) we want to close the drawer on back.
312
- */
313
- if (drawer.isDrawerOpen(navigation) && drawer.shouldCloseDrawerFromBackPress()) {
314
- closeDrawer()
315
- } else {
316
- super .onBackPressed()
317
- }
318
- }
319
-
320
- private fun closeDrawer () {
321
- drawer.closeDrawer(GravityCompat .START )
322
- }
323
-
324
245
override fun onUserInteraction () {
325
246
super .onUserInteraction()
326
247
getCurrentFragment()?.onUserInteraction()
327
248
}
328
249
329
250
private fun getCurrentFragment (): MainNavigationFragment ? {
330
251
return navHostFragment
331
- ? .childFragmentManager
332
- ? .primaryNavigationFragment as ? MainNavigationFragment
252
+ .childFragmentManager
253
+ .primaryNavigationFragment as ? MainNavigationFragment
333
254
}
334
255
335
256
private fun navigateTo (navId : Int ) {
0 commit comments