mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Remove bottom nav behavior and add bottom padding to root controller contents
This commit is contained in:
		| @@ -44,6 +44,7 @@ import eu.kanade.presentation.components.FastScrollLazyColumn | ||||
| import eu.kanade.presentation.components.LoadingScreen | ||||
| import eu.kanade.presentation.components.SwipeRefreshIndicator | ||||
| import eu.kanade.presentation.theme.header | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.presentation.util.topPaddingValues | ||||
| @@ -112,7 +113,7 @@ fun ExtensionContent( | ||||
|     var trustState by remember { mutableStateOf<Extension.Untrusted?>(null) } | ||||
|  | ||||
|     FastScrollLazyColumn( | ||||
|         contentPadding = WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|         contentPadding = bottomNavPaddingValues + WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|     ) { | ||||
|         items( | ||||
|             items = state.items, | ||||
|   | ||||
| @@ -28,6 +28,7 @@ import eu.kanade.presentation.components.EmptyScreen | ||||
| import eu.kanade.presentation.components.LoadingScreen | ||||
| import eu.kanade.presentation.components.ScrollbarLazyColumn | ||||
| import eu.kanade.presentation.theme.header | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.presentation.util.topPaddingValues | ||||
| @@ -68,7 +69,7 @@ fun MigrateSourceList( | ||||
| ) { | ||||
|     ScrollbarLazyColumn( | ||||
|         modifier = Modifier.nestedScroll(nestedScrollInterop), | ||||
|         contentPadding = WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|         contentPadding = bottomNavPaddingValues + WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|     ) { | ||||
|         item(key = "title") { | ||||
|             Text( | ||||
|   | ||||
| @@ -35,6 +35,7 @@ import eu.kanade.presentation.components.EmptyScreen | ||||
| import eu.kanade.presentation.components.LoadingScreen | ||||
| import eu.kanade.presentation.components.ScrollbarLazyColumn | ||||
| import eu.kanade.presentation.theme.header | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.presentation.util.topPaddingValues | ||||
| @@ -92,7 +93,7 @@ fun SourceList( | ||||
| ) { | ||||
|     ScrollbarLazyColumn( | ||||
|         modifier = Modifier.nestedScroll(nestedScrollConnection), | ||||
|         contentPadding = WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|         contentPadding = bottomNavPaddingValues + WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|     ) { | ||||
|         items( | ||||
|             items = state.items, | ||||
|   | ||||
| @@ -50,6 +50,7 @@ fun VerticalFastScroller( | ||||
|     thumbAllowed: () -> Boolean = { true }, | ||||
|     thumbColor: Color = MaterialTheme.colorScheme.primary, | ||||
|     topContentPadding: Dp = Dp.Hairline, | ||||
|     bottomContentPadding: Dp = Dp.Hairline, | ||||
|     endContentPadding: Dp = Dp.Hairline, | ||||
|     content: @Composable () -> Unit, | ||||
| ) { | ||||
| @@ -76,7 +77,8 @@ fun VerticalFastScroller( | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             val heightPx = contentHeight.toFloat() - thumbTopPadding - listState.layoutInfo.afterContentPadding | ||||
|             val thumbBottomPadding = with(LocalDensity.current) { bottomContentPadding.toPx() } | ||||
|             val heightPx = contentHeight.toFloat() - thumbTopPadding - thumbBottomPadding - listState.layoutInfo.afterContentPadding | ||||
|             val thumbHeightPx = with(LocalDensity.current) { ThumbLength.toPx() } | ||||
|             val trackHeightPx = heightPx - thumbHeightPx | ||||
|  | ||||
|   | ||||
| @@ -43,6 +43,7 @@ import eu.kanade.presentation.components.RelativeDateHeader | ||||
| import eu.kanade.presentation.components.ScrollbarLazyColumn | ||||
| import eu.kanade.presentation.history.components.HistoryItem | ||||
| import eu.kanade.presentation.history.components.HistoryItemShimmer | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.presentation.util.shimmerGradient | ||||
| import eu.kanade.presentation.util.topPaddingValues | ||||
| @@ -102,7 +103,7 @@ fun HistoryContent( | ||||
|     ScrollbarLazyColumn( | ||||
|         modifier = Modifier | ||||
|             .nestedScroll(nestedScroll), | ||||
|         contentPadding = WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|         contentPadding = bottomNavPaddingValues + WindowInsets.navigationBars.asPaddingValues() + topPaddingValues, | ||||
|         state = scrollState, | ||||
|     ) { | ||||
|         items(history) { item -> | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.unit.dp | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.plus | ||||
|  | ||||
| @Composable | ||||
| @@ -22,7 +23,7 @@ fun LazyLibraryGrid( | ||||
|     LazyVerticalGrid( | ||||
|         modifier = modifier, | ||||
|         columns = if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns), | ||||
|         contentPadding = PaddingValues(12.dp) + WindowInsets.navigationBars.asPaddingValues(), | ||||
|         contentPadding = bottomNavPaddingValues + PaddingValues(12.dp) + WindowInsets.navigationBars.asPaddingValues(), | ||||
|         verticalArrangement = Arrangement.spacedBy(12.dp), | ||||
|         horizontalArrangement = Arrangement.spacedBy(12.dp), | ||||
|         content = content, | ||||
|   | ||||
| @@ -22,7 +22,9 @@ import eu.kanade.domain.manga.model.MangaCover | ||||
| import eu.kanade.presentation.components.Badge | ||||
| import eu.kanade.presentation.components.BadgeGroup | ||||
| import eu.kanade.presentation.components.TextButton | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.presentation.util.selectedBackground | ||||
| import eu.kanade.presentation.util.verticalPadding | ||||
| import eu.kanade.tachiyomi.R | ||||
| @@ -39,7 +41,7 @@ fun LibraryList( | ||||
|     onGlobalSearchClicked: () -> Unit, | ||||
| ) { | ||||
|     LazyColumn( | ||||
|         contentPadding = WindowInsets.navigationBars.asPaddingValues(), | ||||
|         contentPadding = bottomNavPaddingValues + WindowInsets.navigationBars.asPaddingValues(), | ||||
|     ) { | ||||
|         item { | ||||
|             if (searchQuery.isNullOrEmpty().not()) { | ||||
|   | ||||
| @@ -26,6 +26,7 @@ import eu.kanade.presentation.components.PreferenceRow | ||||
| import eu.kanade.presentation.components.Scaffold | ||||
| import eu.kanade.presentation.components.ScrollbarLazyColumn | ||||
| import eu.kanade.presentation.components.SwitchPreference | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.presentation.util.quantityStringResource | ||||
| import eu.kanade.tachiyomi.R | ||||
| @@ -56,7 +57,7 @@ fun MoreScreen( | ||||
|         }, | ||||
|     ) { paddingValues -> | ||||
|         ScrollbarLazyColumn( | ||||
|             contentPadding = paddingValues + WindowInsets.navigationBars.asPaddingValues(), | ||||
|             contentPadding = bottomNavPaddingValues + paddingValues + WindowInsets.navigationBars.asPaddingValues(), | ||||
|         ) { | ||||
|             item { | ||||
|                 LogoHeader() | ||||
|   | ||||
| @@ -34,9 +34,7 @@ import eu.kanade.presentation.components.MangaBottomActionMenu | ||||
| import eu.kanade.presentation.components.Scaffold | ||||
| import eu.kanade.presentation.components.SwipeRefreshIndicator | ||||
| import eu.kanade.presentation.components.VerticalFastScroller | ||||
| import eu.kanade.presentation.util.NavBarVisibility | ||||
| import eu.kanade.presentation.util.isScrollingDown | ||||
| import eu.kanade.presentation.util.isScrollingUp | ||||
| import eu.kanade.presentation.util.bottomNavPaddingValues | ||||
| import eu.kanade.presentation.util.plus | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.download.model.Download | ||||
| @@ -56,7 +54,6 @@ fun UpdateScreen( | ||||
|     onDownloadChapter: (List<UpdatesItem>, ChapterDownloadAction) -> Unit, | ||||
|     onUpdateLibrary: () -> Unit, | ||||
|     onBackClicked: () -> Unit, | ||||
|     toggleNavBarVisibility: (NavBarVisibility) -> Unit, | ||||
|     // For bottom action menu | ||||
|     onMultiBookmarkClicked: (List<UpdatesItem>, bookmark: Boolean) -> Unit, | ||||
|     onMultiMarkAsReadClicked: (List<UpdatesItem>, read: Boolean) -> Unit, | ||||
| @@ -86,13 +83,6 @@ fun UpdateScreen( | ||||
|     // First and last selected index in list | ||||
|     val selectedPositions = remember(uiModels) { arrayOf(-1, -1) } | ||||
|  | ||||
|     when { | ||||
|         selected.isEmpty() && | ||||
|             updatesListState.isScrollingUp() -> toggleNavBarVisibility(NavBarVisibility.SHOW) | ||||
|         selected.isNotEmpty() || | ||||
|             updatesListState.isScrollingDown() -> toggleNavBarVisibility(NavBarVisibility.HIDE) | ||||
|     } | ||||
|  | ||||
|     val internalOnBackPressed = { | ||||
|         if (selected.isNotEmpty()) { | ||||
|             selected.clear() | ||||
| @@ -133,7 +123,7 @@ fun UpdateScreen( | ||||
|             ) | ||||
|         }, | ||||
|     ) { contentPadding -> | ||||
|         val contentPaddingWithNavBar = contentPadding + | ||||
|         val contentPaddingWithNavBar = bottomNavPaddingValues + contentPadding + | ||||
|             WindowInsets.navigationBars.only(WindowInsetsSides.Bottom).asPaddingValues() | ||||
|  | ||||
|         SwipeRefresh( | ||||
| @@ -153,6 +143,7 @@ fun UpdateScreen( | ||||
|                 VerticalFastScroller( | ||||
|                     listState = updatesListState, | ||||
|                     topContentPadding = contentPaddingWithNavBar.calculateTopPadding(), | ||||
|                     bottomContentPadding = contentPaddingWithNavBar.calculateBottomPadding(), | ||||
|                     endContentPadding = contentPaddingWithNavBar.calculateEndPadding(LocalLayoutDirection.current), | ||||
|                 ) { | ||||
|                     LazyColumn( | ||||
|   | ||||
| @@ -4,13 +4,12 @@ import androidx.compose.foundation.layout.PaddingValues | ||||
| import androidx.compose.ui.unit.dp | ||||
|  | ||||
| private val horizontal = 16.dp | ||||
|  | ||||
| private val vertical = 8.dp | ||||
|  | ||||
| val horizontalPadding = horizontal | ||||
|  | ||||
| val verticalPadding = vertical | ||||
|  | ||||
| val topPaddingValues = PaddingValues(top = vertical) | ||||
| val bottomNavPaddingValues = PaddingValues(bottom = 96.dp) | ||||
|  | ||||
| const val ReadItemAlpha = .38f | ||||
|   | ||||
| @@ -1,13 +0,0 @@ | ||||
| package eu.kanade.presentation.util | ||||
|  | ||||
| enum class NavBarVisibility { | ||||
|     SHOW, | ||||
|     HIDE | ||||
| } | ||||
|  | ||||
| fun NavBarVisibility.toBoolean(): Boolean { | ||||
|     return when (this) { | ||||
|         NavBarVisibility.SHOW -> true | ||||
|         NavBarVisibility.HIDE -> false | ||||
|     } | ||||
| } | ||||
| @@ -10,8 +10,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||||
| import eu.kanade.presentation.components.ChapterDownloadAction | ||||
| import eu.kanade.presentation.components.LoadingScreen | ||||
| import eu.kanade.presentation.updates.UpdateScreen | ||||
| import eu.kanade.presentation.util.NavBarVisibility | ||||
| import eu.kanade.presentation.util.toBoolean | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.download.DownloadService | ||||
| import eu.kanade.tachiyomi.data.download.model.Download | ||||
| @@ -49,7 +47,6 @@ class UpdatesController : | ||||
|                     onDownloadChapter = this::downloadChapters, | ||||
|                     onUpdateLibrary = this::updateLibrary, | ||||
|                     onBackClicked = this::onBackClicked, | ||||
|                     toggleNavBarVisibility = this::toggleNavBarVisibility, | ||||
|                     // For bottom action menu | ||||
|                     onMultiBookmarkClicked = { updatesItems, bookmark -> | ||||
|                         presenter.bookmarkUpdates(updatesItems, bookmark) | ||||
| @@ -80,15 +77,6 @@ class UpdatesController : | ||||
|         (activity as? MainActivity)?.moveToStartScreen() | ||||
|     } | ||||
|  | ||||
|     private fun toggleNavBarVisibility(navBarVisibility: NavBarVisibility) { | ||||
|         val showNavBar = navBarVisibility.toBoolean() | ||||
|         (activity as? MainActivity)?.showBottomNav(showNavBar) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Download selected items | ||||
|      * @param items list of selected [UpdatesItem]s | ||||
|      */ | ||||
|     private fun downloadChapters(items: List<UpdatesItem>, action: ChapterDownloadAction) { | ||||
|         if (items.isEmpty()) return | ||||
|         viewScope.launch { | ||||
|   | ||||
| @@ -1,106 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.widget | ||||
|  | ||||
| import android.animation.ValueAnimator | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.view.animation.DecelerateInterpolator | ||||
| import androidx.appcompat.widget.Toolbar | ||||
| import androidx.coordinatorlayout.widget.CoordinatorLayout | ||||
| import androidx.core.view.ViewCompat | ||||
| import com.google.android.material.appbar.AppBarLayout | ||||
| import com.google.android.material.bottomnavigation.BottomNavigationView | ||||
| import eu.kanade.tachiyomi.util.system.animatorDurationScale | ||||
| import eu.kanade.tachiyomi.util.view.findChild | ||||
| import kotlin.math.roundToLong | ||||
|  | ||||
| /** | ||||
|  * Hide behavior similar to app bar for [BottomNavigationView] | ||||
|  */ | ||||
| class HideBottomNavigationOnScrollBehavior @JvmOverloads constructor( | ||||
|     context: Context? = null, | ||||
|     attrs: AttributeSet? = null, | ||||
| ) : CoordinatorLayout.Behavior<BottomNavigationView>(context, attrs) { | ||||
|  | ||||
|     @ViewCompat.NestedScrollType | ||||
|     private var lastStartedType: Int = 0 | ||||
|  | ||||
|     private var offsetAnimator: ValueAnimator? = null | ||||
|  | ||||
|     private var dyRatio = 1F | ||||
|  | ||||
|     override fun layoutDependsOn(parent: CoordinatorLayout, child: BottomNavigationView, dependency: View): Boolean { | ||||
|         return dependency is AppBarLayout | ||||
|     } | ||||
|  | ||||
|     override fun onDependentViewChanged( | ||||
|         parent: CoordinatorLayout, | ||||
|         child: BottomNavigationView, | ||||
|         dependency: View, | ||||
|     ): Boolean { | ||||
|         val toolbarSize = (dependency as ViewGroup).findChild<Toolbar>()?.height ?: 0 | ||||
|         dyRatio = if (toolbarSize > 0) { | ||||
|             child.height.toFloat() / toolbarSize | ||||
|         } else { | ||||
|             1F | ||||
|         } | ||||
|         return false | ||||
|     } | ||||
|  | ||||
|     override fun onStartNestedScroll( | ||||
|         coordinatorLayout: CoordinatorLayout, | ||||
|         child: BottomNavigationView, | ||||
|         directTargetChild: View, | ||||
|         target: View, | ||||
|         axes: Int, | ||||
|         type: Int, | ||||
|     ): Boolean { | ||||
|         if (axes != ViewCompat.SCROLL_AXIS_VERTICAL) { | ||||
|             return false | ||||
|         } | ||||
|         lastStartedType = type | ||||
|         offsetAnimator?.cancel() | ||||
|         return true | ||||
|     } | ||||
|  | ||||
|     override fun onNestedPreScroll( | ||||
|         coordinatorLayout: CoordinatorLayout, | ||||
|         child: BottomNavigationView, | ||||
|         target: View, | ||||
|         dx: Int, | ||||
|         dy: Int, | ||||
|         consumed: IntArray, | ||||
|         type: Int, | ||||
|     ) { | ||||
|         super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type) | ||||
|         child.translationY = (child.translationY + (dy * dyRatio)).coerceIn(0F, child.height.toFloat()) | ||||
|     } | ||||
|  | ||||
|     override fun onStopNestedScroll( | ||||
|         coordinatorLayout: CoordinatorLayout, | ||||
|         child: BottomNavigationView, | ||||
|         target: View, | ||||
|         type: Int, | ||||
|     ) { | ||||
|         if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) { | ||||
|             animateBottomNavigationVisibility(child, child.translationY < child.height / 2) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun animateBottomNavigationVisibility(child: BottomNavigationView, isVisible: Boolean) { | ||||
|         offsetAnimator?.cancel() | ||||
|         offsetAnimator = ValueAnimator().apply { | ||||
|             interpolator = DecelerateInterpolator() | ||||
|             duration = (150 * child.context.animatorDurationScale).roundToLong() | ||||
|             addUpdateListener { | ||||
|                 child.translationY = it.animatedValue as Float | ||||
|             } | ||||
|         } | ||||
|         offsetAnimator?.setFloatValues( | ||||
|             child.translationY, | ||||
|             if (isVisible) 0F else child.height.toFloat(), | ||||
|         ) | ||||
|         offsetAnimator?.start() | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user