Skip to content
This repository has been archived by the owner on Jan 5, 2023. It is now read-only.

Commit

Permalink
Make app go edge-to-edge
Browse files Browse the repository at this point in the history
This CL makes the majority of the app draw from top
to bottom, behind the status and navigation bars.

I haven't touch session or speaker details yet,
that will come in a later CL.

The custom build of MDC is because it includes
an upcoming bug fix in AppBarLayout which will
be available in v1.1.0-alpha05.

Change-Id: I61ecf1ea6e17e1868388d18fbdd29f34f1559e8a
  • Loading branch information
Chris Banes authored and thagikura committed Aug 14, 2019
1 parent 6c22545 commit 84ef129
Show file tree
Hide file tree
Showing 35 changed files with 1,007 additions and 474 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Expand Up @@ -65,7 +65,7 @@ buildscript {
legacySupportVersion = '1.0.0'
lifecycleVersion = '2.0.0'
lottieVersion = "2.5.1"
materialVersion = '1.1.0-alpha04'
materialVersion = '1.1.0-alpha04-cl237931928'
mockitoVersion = "2.8.9"
mockitoKotlinVersion = "1.5.0"
navigationVersion = "2.0.0-rc02"
Expand Down Expand Up @@ -121,6 +121,7 @@ allprojects {
maven {
url "${rootProject.projectDir}/../../../prebuilts/fullsdk/linux/extras/support/m2repository"
}
maven { url "${rootProject.projectDir}/prebuilts/m2repository" }

flatDir {
dirs "libs"
Expand Down
6 changes: 2 additions & 4 deletions mobile/src/main/AndroidManifest.xml
Expand Up @@ -59,8 +59,7 @@
</activity>

<activity
android:name=".ui.MainActivity"
android:theme="@style/AppTheme.NoActionBar" />
android:name=".ui.MainActivity" />

<activity
android:name=".ui.onboarding.OnboardingActivity"
Expand All @@ -77,8 +76,7 @@
android:theme="@style/AppTheme.Speaker" />

<activity
android:name=".ui.map.MapActivity"
android:theme="@style/AppTheme.NoActionBar" />
android:name=".ui.map.MapActivity" />

<!-- This activity alias lets us change the main entry point without breaking launcher
shortcuts. DO NOT change its android:name attribute. -->
Expand Down
Expand Up @@ -20,8 +20,10 @@ import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.FrameLayout
import android.widget.Toast
import androidx.core.view.GravityCompat
import androidx.core.view.updatePadding
import androidx.drawerlayout.widget.DrawerLayout
import androidx.drawerlayout.widget.DrawerLayout.DrawerListener
import androidx.lifecycle.Observer
Expand All @@ -30,9 +32,9 @@ import com.firebase.ui.auth.IdpResponse
import com.google.android.material.navigation.NavigationView
import com.google.samples.apps.iosched.R
import com.google.samples.apps.iosched.databinding.NavigationHeaderBinding
import com.google.samples.apps.iosched.shared.di.MapFeatureEnabledFlag
import com.google.samples.apps.iosched.shared.di.ExploreArEnabledFlag
import com.google.samples.apps.iosched.shared.di.FeedFeatureEnabledFlag
import com.google.samples.apps.iosched.shared.di.MapFeatureEnabledFlag
import com.google.samples.apps.iosched.shared.result.EventObserver
import com.google.samples.apps.iosched.shared.util.inTransaction
import com.google.samples.apps.iosched.shared.util.viewModelProvider
Expand All @@ -45,6 +47,9 @@ import com.google.samples.apps.iosched.ui.schedule.ScheduleFragment
import com.google.samples.apps.iosched.ui.settings.SettingsFragment
import com.google.samples.apps.iosched.ui.signin.SignInDialogFragment
import com.google.samples.apps.iosched.ui.signin.SignOutDialogFragment
import com.google.samples.apps.iosched.util.HeightTopWindowInsetsListener
import com.google.samples.apps.iosched.util.NoopWindowInsetsListener
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import com.google.samples.apps.iosched.util.signin.FirebaseAuthErrorCodeConverter
import com.google.samples.apps.iosched.util.updateForTheme
import dagger.android.support.DaggerAppCompatActivity
Expand Down Expand Up @@ -90,7 +95,10 @@ class MainActivity : DaggerAppCompatActivity(), NavigationHost, DrawerListener {

private lateinit var drawer: DrawerLayout
private lateinit var navigation: NavigationView
private lateinit var statusScrim: View

private lateinit var navHeaderBinding: NavigationHeaderBinding
private lateinit var content: FrameLayout

private lateinit var currentFragment: MainNavigationFragment
private var currentNavId = NAV_ID_NONE
Expand All @@ -104,10 +112,20 @@ class MainActivity : DaggerAppCompatActivity(), NavigationHost, DrawerListener {
updateForTheme(viewModel.currentTheme)

setContentView(R.layout.activity_main)
drawer = findViewById(R.id.drawer)

drawer = findViewById(R.id.drawer)
drawer.addDrawerListener(this)

content = findViewById(R.id.content_container)
content.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// Make the content ViewGroup ignore insets so that it does not use the default padding
content.setOnApplyWindowInsetsListener(NoopWindowInsetsListener)

statusScrim = findViewById(R.id.status_bar_scrim)
statusScrim.setOnApplyWindowInsetsListener(HeightTopWindowInsetsListener)

navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater).apply {
viewModel = this@MainActivity.viewModel
lifecycleOwner = this@MainActivity
Expand All @@ -127,6 +145,11 @@ class MainActivity : DaggerAppCompatActivity(), NavigationHost, DrawerListener {
}
}

// Update the Navigation header view to pad itself down
navHeaderBinding.root.doOnApplyWindowInsets { v, insets, padding ->
v.updatePadding(top = padding.top + insets.systemWindowInsetTop)
}

if (savedInstanceState == null) {
// default to showing Schedule
val initialNavId = intent.getIntExtra(EXTRA_NAVIGATION_ID, R.id.navigation_schedule)
Expand Down
Expand Up @@ -20,6 +20,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updatePadding
import androidx.databinding.BindingAdapter
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.RecyclerView
Expand All @@ -28,6 +29,7 @@ import com.google.samples.apps.iosched.model.Block
import com.google.samples.apps.iosched.shared.util.viewModelProvider
import com.google.samples.apps.iosched.ui.MainNavigationFragment
import com.google.samples.apps.iosched.util.clearDecorations
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import org.threeten.bp.ZoneId
import javax.inject.Inject

Expand All @@ -46,6 +48,10 @@ class AgendaFragment : MainNavigationFragment() {
binding = FragmentAgendaBinding.inflate(inflater, container, false).apply {
lifecycleOwner = viewLifecycleOwner
}
// Pad the bottom of the RecyclerView so that the content scrolls up above the nav bar
binding.recyclerView.doOnApplyWindowInsets { v, insets, padding ->
v.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom)
}
return binding.root
}

Expand All @@ -61,11 +67,10 @@ fun agendaItems(recyclerView: RecyclerView, list: List<Block>?, timeZoneId: Zone
if (recyclerView.adapter == null) {
recyclerView.adapter = AgendaAdapter()
}
val adapter = (recyclerView.adapter as AgendaAdapter).apply {
(recyclerView.adapter as AgendaAdapter).apply {
this.submitList(list ?: emptyList())
this.timeZoneId = timeZoneId ?: ZoneId.systemDefault()
}

// Recreate the decoration used for the sticky date headers
recyclerView.clearDecorations()
if (list != null && list.isNotEmpty()) {
Expand Down
Expand Up @@ -21,6 +21,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.databinding.BindingAdapter
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
Expand All @@ -34,6 +36,7 @@ import com.google.samples.apps.iosched.shared.util.viewModelProvider
import com.google.samples.apps.iosched.ui.MainNavigationFragment
import com.google.samples.apps.iosched.ui.messages.SnackbarMessageManager
import com.google.samples.apps.iosched.ui.setUpSnackbar
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import kotlinx.android.synthetic.main.fragment_feed.toolbar
import timber.log.Timber
import javax.inject.Inject
Expand Down Expand Up @@ -63,6 +66,18 @@ class FeedFragment : MainNavigationFragment() {
viewModel = model
}

binding.root.doOnApplyWindowInsets { _, insets, _ ->
binding.statusBar.run {
layoutParams.height = insets.systemWindowInsetTop
isVisible = layoutParams.height > 0
requestLayout()
}
}

binding.recyclerView.doOnApplyWindowInsets { v, insets, padding ->
v.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom)
}

setUpSnackbar(model.snackBarMessage, binding.snackbar, snackbarMessageManager)

model.errorMessage.observe(this, Observer { message ->
Expand Down
Expand Up @@ -24,6 +24,7 @@ import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import androidx.core.view.updatePaddingRelative
import androidx.databinding.BindingAdapter
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
Expand All @@ -33,6 +34,7 @@ import com.google.samples.apps.iosched.shared.util.TimeUtils
import com.google.samples.apps.iosched.shared.util.viewModelProvider
import com.google.samples.apps.iosched.ui.messages.SnackbarMessageManager
import com.google.samples.apps.iosched.ui.setUpSnackbar
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import com.google.samples.apps.iosched.widget.FadingSnackbar
import dagger.android.support.DaggerFragment
import javax.inject.Inject
Expand All @@ -54,6 +56,12 @@ class EventFragment : DaggerFragment() {
viewModel = eventInfoViewModel
lifecycleOwner = viewLifecycleOwner
}

// Pad the bottom of the content so that it is above the nav bar
binding.content.doOnApplyWindowInsets { v, insets, padding ->
v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom)
}

val snackbarLayout = requireActivity().findViewById<FadingSnackbar>(R.id.snackbar)
setUpSnackbar(eventInfoViewModel.snackBarMessage, snackbarLayout, snackbarMessageManager)

Expand Down
Expand Up @@ -20,7 +20,9 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updatePaddingRelative
import com.google.samples.apps.iosched.R
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import dagger.android.support.DaggerFragment

class TravelFragment : DaggerFragment() {
Expand All @@ -32,4 +34,13 @@ class TravelFragment : DaggerFragment() {
): View? {
return inflater.inflate(R.layout.fragment_info_travel, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

// Pad the bottom of the ScrollView so that it scrolls up above the nav bar
view.doOnApplyWindowInsets { v, insets, padding ->
v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom)
}
}
}
Expand Up @@ -17,6 +17,8 @@
package com.google.samples.apps.iosched.ui.map

import android.Manifest
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.app.Dialog
import android.content.pm.PackageManager
import android.os.Bundle
Expand All @@ -25,7 +27,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.widget.NestedScrollView
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.Observer
Expand All @@ -38,6 +45,7 @@ import com.google.samples.apps.iosched.databinding.FragmentMapBinding
import com.google.samples.apps.iosched.shared.analytics.AnalyticsHelper
import com.google.samples.apps.iosched.shared.util.viewModelProvider
import com.google.samples.apps.iosched.ui.MainNavigationFragment
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import com.google.samples.apps.iosched.widget.BottomSheetBehavior
import com.google.samples.apps.iosched.widget.BottomSheetBehavior.BottomSheetCallback
import org.threeten.bp.Instant
Expand Down Expand Up @@ -124,13 +132,58 @@ class MapFragment : MainNavigationFragment() {
}
binding.expandIcon.animate().rotationX(rotation).start()

when (newState) {
BottomSheetBehavior.STATE_EXPANDED -> {
binding.descriptionScrollview.animate()
.setDuration(150)
.alpha(1f)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {
binding.descriptionScrollview.isVisible = true
}
})
.start()
}
BottomSheetBehavior.STATE_COLLAPSED,
BottomSheetBehavior.STATE_HIDDEN -> {
binding.descriptionScrollview.animate()
.alpha(0f)
.setDuration(150)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
binding.descriptionScrollview.isInvisible = true
}
})
.start()
}
}

// Analytics
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
viewModel.logViewedMarkerDetails()
}
}
})

binding.root.doOnApplyWindowInsets { _, insets, _ ->
binding.statusBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = insets.systemWindowInsetTop
}
binding.statusBar.isVisible = true
binding.statusBar.requestLayout()

// Update the Map padding so that the copyright, etc is not displayed in nav bar
binding.map.getMapAsync {
it.setPadding(0, 0, 0, insets.systemWindowInsetBottom)
}
}

val originalPeekHeight = bottomSheetBehavior.peekHeight
binding.bottomSheet.doOnApplyWindowInsets { v, insets, _ ->
v.updatePadding(bottom = insets.systemWindowInsetBottom)
bottomSheetBehavior.peekHeight = insets.systemWindowInsetBottom + originalPeekHeight
}

// Make the header clickable.
binding.clickable.setOnClickListener {
if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
Expand Down
Expand Up @@ -23,6 +23,7 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DefaultItemAnimator
Expand Down Expand Up @@ -50,6 +51,7 @@ import com.google.samples.apps.iosched.ui.signin.NotificationsPreferenceDialogFr
import com.google.samples.apps.iosched.ui.signin.SignInDialogFragment
import com.google.samples.apps.iosched.ui.signin.SignOutDialogFragment
import com.google.samples.apps.iosched.util.clearDecorations
import com.google.samples.apps.iosched.util.doOnApplyWindowInsets
import com.google.samples.apps.iosched.util.executeAfter
import com.google.samples.apps.iosched.util.fabVisibility
import com.google.samples.apps.iosched.widget.BottomSheetBehavior
Expand Down Expand Up @@ -149,6 +151,11 @@ class ScheduleFragment : MainNavigationFragment() {
}
})

// Pad the bottom of the RecyclerView so that the content scrolls up above the nav bar
binding.recyclerview.doOnApplyWindowInsets { v, insets, padding ->
v.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom)
}

// Session list configuration
scheduleAdapter = ScheduleAdapter(
scheduleViewModel,
Expand Down

0 comments on commit 84ef129

Please sign in to comment.