Initial tablet NavigationRailView implementation

TODO:
- Make the side nav go beside the toolbar too
- Extract out common main_activity stuff to remove duplicated code

(cherry picked from commit de35a4c62a7636650b1ff88c33de0cc0695f6411)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
#	app/src/main/res/layout/main_activity.xml
This commit is contained in:
arkon 2021-05-14 09:14:42 -04:00 committed by Jobobby04
parent f5a90d46ec
commit 35879921dd
8 changed files with 167 additions and 55 deletions

View File

@ -147,7 +147,7 @@ dependencies {
implementation("androidx.work:work-runtime-ktx:2.5.0") implementation("androidx.work:work-runtime-ktx:2.5.0")
// UI library // UI library
implementation("com.google.android.material:material:1.3.0") implementation("com.google.android.material:material:1.4.0-beta01")
"standardImplementation"("com.google.firebase:firebase-core:19.0.0") "standardImplementation"("com.google.firebase:firebase-core:19.0.0")

View File

@ -416,7 +416,7 @@ class LibraryController(
actionMode!!, actionMode!!,
R.menu.library_selection R.menu.library_selection
) { onActionItemClicked(it!!) } ) { onActionItemClicked(it!!) }
(activity as? MainActivity)?.showBottomNav(visible = false, collapse = true) (activity as? MainActivity)?.showNav(visible = false, collapse = true)
} }
} }
@ -564,7 +564,7 @@ class LibraryController(
selectionRelay.call(LibrarySelectionEvent.Cleared()) selectionRelay.call(LibrarySelectionEvent.Cleared())
binding.actionToolbar.hide() binding.actionToolbar.hide()
(activity as? MainActivity)?.showBottomNav(visible = true, collapse = true) (activity as? MainActivity)?.showNav(visible = true, collapse = true)
actionMode = null actionMode = null
} }

View File

@ -25,12 +25,10 @@ import com.bluelinelabs.conductor.Router
import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.RouterTransaction
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior import com.google.android.material.behavior.HideBottomViewOnScrollBehavior
import com.google.android.material.bottomnavigation.LabelVisibilityMode.LABEL_VISIBILITY_LABELED import com.google.android.material.navigation.NavigationBarView
import com.google.android.material.bottomnavigation.LabelVisibilityMode.LABEL_VISIBILITY_SELECTED
import dev.chrisbanes.insetter.applyInsetter import dev.chrisbanes.insetter.applyInsetter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.preference.PreferenceKeys.bottomBarLabels
import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.databinding.MainActivityBinding import eu.kanade.tachiyomi.databinding.MainActivityBinding
import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
@ -85,7 +83,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
} }
lateinit var tabAnimator: ViewHeightAnimator lateinit var tabAnimator: ViewHeightAnimator
private lateinit var bottomNavAnimator: ViewHeightAnimator private var bottomNavAnimator: ViewHeightAnimator? = null
private var isConfirmingExit: Boolean = false private var isConfirmingExit: Boolean = false
private var isHandlingShortcut: Boolean = false private var isHandlingShortcut: Boolean = false
@ -137,7 +135,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
margin() margin()
} }
} }
binding.bottomNav.applyInsetter { binding.bottomNav?.applyInsetter {
type(navigationBars = true) { type(navigationBars = true) {
padding() padding()
} }
@ -159,23 +157,26 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
} }
tabAnimator = ViewHeightAnimator(binding.tabs, 0L) tabAnimator = ViewHeightAnimator(binding.tabs, 0L)
bottomNavAnimator = ViewHeightAnimator(binding.bottomNav)
// If bottom nav is hidden, make it visible again when the app bar is expanded if (binding.bottomNav != null) {
binding.appbar.addOnOffsetChangedListener( bottomNavAnimator = ViewHeightAnimator(binding.bottomNav!!)
AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
if (verticalOffset == 0) { // If bottom nav is hidden, make it visible again when the app bar is expanded
showBottomNav(true) binding.appbar.addOnOffsetChangedListener(
AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
if (verticalOffset == 0) {
showNav(true)
}
} }
} )
)
// Set behavior of bottom nav // Set behavior of bottom nav
preferences.hideBottomBar() preferences.hideBottomBar()
.asImmediateFlow { setBottomNavBehaviorOnScroll() } .asImmediateFlow { setBottomNavBehaviorOnScroll() }
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
}
binding.bottomNav.setOnNavigationItemSelectedListener { item -> nav.setOnItemSelectedListener { item ->
val id = item.itemId val id = item.itemId
val currentRoot = router.backstack.firstOrNull() val currentRoot = router.backstack.firstOrNull()
@ -318,9 +319,9 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
private fun setExtensionsBadge() { private fun setExtensionsBadge() {
val updates = preferences.extensionUpdatesCount().get() val updates = preferences.extensionUpdatesCount().get()
if (updates > 0) { if (updates > 0) {
binding.bottomNav.getOrCreateBadge(R.id.nav_browse).number = updates nav.getOrCreateBadge(R.id.nav_browse).number = updates
} else { } else {
binding.bottomNav.removeBadge(R.id.nav_browse) nav.removeBadge(R.id.nav_browse)
} }
} }
@ -412,7 +413,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
super.onDestroy() super.onDestroy()
// Binding sometimes isn't actually instantiated yet somehow // Binding sometimes isn't actually instantiated yet somehow
binding?.bottomNav.setOnNavigationItemSelectedListener(null) nav.setOnItemSelectedListener(null)
binding?.toolbar.setNavigationOnClickListener(null) binding?.toolbar.setNavigationOnClickListener(null)
} }
@ -447,7 +448,7 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
fun setSelectedNavItem(itemId: Int) { fun setSelectedNavItem(itemId: Int) {
if (!isFinishing) { if (!isFinishing) {
binding.bottomNav.selectedItemId = itemId nav.selectedItemId = itemId
} }
} }
@ -469,11 +470,11 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
binding.appbar.setExpanded(true) binding.appbar.setExpanded(true)
if ((from == null || from is RootController) && to !is RootController) { if ((from == null || from is RootController) && to !is RootController) {
showBottomNav(visible = false, collapse = true) showNav(visible = false, collapse = true)
} }
if (to is RootController) { if (to is RootController) {
// Always show bottom nav again when returning to a RootController // Always show bottom nav again when returning to a RootController
showBottomNav(visible = true, collapse = from !is RootController) showNav(visible = true, collapse = from !is RootController)
} }
if (from is TabbedController) { if (from is TabbedController) {
@ -509,25 +510,32 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
} }
} }
fun showBottomNav(visible: Boolean, collapse: Boolean = false) { fun showNav(visible: Boolean, collapse: Boolean = false) {
val layoutParams = binding.bottomNav.layoutParams as CoordinatorLayout.LayoutParams binding.bottomNav?.let {
val bottomViewNavigationBehavior = layoutParams.behavior as? HideBottomViewOnScrollBehavior val layoutParams = it.layoutParams as CoordinatorLayout.LayoutParams
if (visible) { val bottomViewNavigationBehavior =
if (collapse) { layoutParams.behavior as? HideBottomViewOnScrollBehavior
bottomNavAnimator.expand() if (visible) {
val navUpdates = binding.bottomNav.menu.findItem(R.id.nav_updates) if (collapse) {
navUpdates.isVisible = !preferences.hideUpdatesButton().get() bottomNavAnimator?.expand()
val navHistory = binding.bottomNav.menu.findItem(R.id.nav_history) val navUpdates = it.menu.findItem(R.id.nav_updates)
navHistory.isVisible = !preferences.hideHistoryButton().get() navUpdates.isVisible = !preferences.hideUpdatesButton().get()
} val navHistory = it.menu.findItem(R.id.nav_history)
navHistory.isVisible = !preferences.hideHistoryButton().get()
}
bottomViewNavigationBehavior?.slideUp(binding.bottomNav) bottomViewNavigationBehavior?.slideUp(it)
} else { } else {
if (collapse) { if (collapse) {
bottomNavAnimator.collapse() bottomNavAnimator?.collapse()
} }
bottomViewNavigationBehavior?.slideDown(binding.bottomNav) bottomViewNavigationBehavior?.slideDown(it)
}
}
binding.sideNav?.let {
it.isVisible = visible
} }
} }
@ -550,9 +558,9 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
} }
private fun setBottomNavBehaviorOnScroll() { private fun setBottomNavBehaviorOnScroll() {
showBottomNav(visible = true) showNav(visible = true)
binding.bottomNav.updateLayoutParams<CoordinatorLayout.LayoutParams> { binding.bottomNav?.updateLayoutParams<CoordinatorLayout.LayoutParams> {
behavior = when { behavior = when {
preferences.hideBottomBar().get() -> HideBottomViewOnScrollBehavior<View>() preferences.hideBottomBar().get() -> HideBottomViewOnScrollBehavior<View>()
else -> null else -> null
@ -560,11 +568,16 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
} }
} }
private val nav: NavigationBarView
get() = binding.bottomNav ?: binding.sideNav!!
private fun setBottomNavLabelVisibility() { private fun setBottomNavLabelVisibility() {
if (preferences.bottomBarLabels().get()) { binding.bottomNav?.let {
binding.bottomNav.labelVisibilityMode = LABEL_VISIBILITY_LABELED if (preferences.bottomBarLabels().get()) {
} else { it.labelVisibilityMode = NavigationBarView.LABEL_VISIBILITY_LABELED
binding.bottomNav.labelVisibilityMode = LABEL_VISIBILITY_SELECTED } else {
it.labelVisibilityMode = NavigationBarView.LABEL_VISIBILITY_SELECTED
}
} }
} }

View File

@ -182,7 +182,7 @@ class UpdatesController :
actionMode!!, actionMode!!,
R.menu.updates_chapter_selection R.menu.updates_chapter_selection
) { onActionItemClicked(it!!) } ) { onActionItemClicked(it!!) }
(activity as? MainActivity)?.showBottomNav(visible = false, collapse = true) (activity as? MainActivity)?.showNav(visible = false, collapse = true)
} }
toggleSelection(position) toggleSelection(position)
@ -380,7 +380,7 @@ class UpdatesController :
adapter?.clearSelection() adapter?.clearSelection()
binding.actionToolbar.hide() binding.actionToolbar.hide()
(activity as? MainActivity)?.showBottomNav(visible = true, collapse = true) (activity as? MainActivity)?.showNav(visible = true, collapse = true)
actionMode = null actionMode = null
} }

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<eu.kanade.tachiyomi.widget.ElevationAppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme"
app:layout_scrollFlags="scroll|enterAlways" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
style="@style/Theme.Widget.Tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/downloaded_only"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/green"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="4dp"
android:text="@string/label_downloaded_only"
android:textColor="@color/md_white_1000" />
</FrameLayout>
<FrameLayout
android:id="@+id/incognito_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/md_grey_800"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="4dp"
android:text="@string/pref_incognito_mode"
android:textColor="@color/md_white_1000" />
</FrameLayout>
</eu.kanade.tachiyomi.widget.ElevationAppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.navigationrail.NavigationRailView
android:id="@+id/side_nav"
style="@style/Widget.MaterialComponents.NavigationRailView.Colored"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:itemIconTint="@color/nav_selector"
app:itemTextColor="@color/nav_selector"
app:labelVisibilityMode="labeled"
app:menu="@menu/main_nav" />
<com.bluelinelabs.conductor.ChangeHandlerFrameLayout
android:id="@+id/controller_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/root_fab"
style="@style/Theme.Widget.FAB"
android:visibility="gone"
tools:icon="@drawable/ic_add_24dp"
tools:text="Action"
tools:visibility="visible" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -85,9 +85,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
app:itemIconTint="@color/bottom_nav_selector" app:itemIconTint="@color/nav_selector"
app:itemTextColor="@color/bottom_nav_selector" app:itemTextColor="@color/nav_selector"
app:layout_insetEdge="bottom" app:layout_insetEdge="bottom"
app:menu="@menu/bottom_nav" /> app:menu="@menu/main_nav" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>