Option to Auto hide bottom nav while scrolling

This commit is contained in:
Jays2Kings 2021-03-20 19:21:24 -04:00
parent 0b432ae87f
commit a14c2d49db
14 changed files with 195 additions and 74 deletions

View File

@ -153,6 +153,8 @@ object PreferenceKeys {
const val alwaysShowChapterTransition = "always_show_chapter_transition" const val alwaysShowChapterTransition = "always_show_chapter_transition"
const val hideBottomNavOnScroll = "hide_bottom_nav_on_scroll"
const val enableDoh = "enable_doh" const val enableDoh = "enable_doh"
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId" fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"

View File

@ -289,5 +289,7 @@ class PreferencesHelper(val context: Context) {
fun shownHopperSwipeTutorial() = flowPrefs.getBoolean("shown_hopper_swipe", false) fun shownHopperSwipeTutorial() = flowPrefs.getBoolean("shown_hopper_swipe", false)
fun hideBottomNavOnScroll() = flowPrefs.getBoolean(Keys.hideBottomNavOnScroll, true)
fun enableDoh() = prefs.getBoolean(Keys.enableDoh, false) fun enableDoh() = prefs.getBoolean(Keys.enableDoh, false)
} }

View File

@ -9,16 +9,18 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.source.SourceController import eu.kanade.tachiyomi.ui.source.SourceController
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.util.view.collapse import eu.kanade.tachiyomi.util.view.collapse
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.view.expand import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.isExpanded import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.android.synthetic.main.extensions_bottom_sheet.view.* import kotlinx.android.synthetic.main.extensions_bottom_sheet.view.*
import kotlinx.android.synthetic.main.main_activity.*
class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LinearLayout(context, attrs), LinearLayout(context, attrs),
@ -51,9 +53,12 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
ext_recycler.adapter = adapter ext_recycler.adapter = adapter
ext_recycler.setHasFixedSize(true) ext_recycler.setHasFixedSize(true)
ext_recycler.addItemDecoration(ExtensionDividerItemDecoration(context)) ext_recycler.addItemDecoration(ExtensionDividerItemDecoration(context))
ext_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
adapter?.fastScroller = fast_scroller adapter?.fastScroller = fast_scroller
this.controller = controller this.controller = controller
ext_recycler.doOnApplyWindowInsets { view, _, _ ->
val bottomBar = (this@ExtensionBottomSheet.controller.activity as? MainActivity)?.bottom_nav
view.updatePaddingRelative(bottom = bottomBar?.height ?: 0)
}
presenter.onCreate() presenter.onCreate()
updateExtTitle() updateExtTitle()

View File

@ -69,14 +69,15 @@ import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getBottomGestureInsets
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
import eu.kanade.tachiyomi.util.view.collapse import eu.kanade.tachiyomi.util.view.collapse
import eu.kanade.tachiyomi.util.view.expand import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.getItemView import eu.kanade.tachiyomi.util.view.getItemView
import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.hide import eu.kanade.tachiyomi.util.view.hide
import eu.kanade.tachiyomi.util.view.invisible
import eu.kanade.tachiyomi.util.view.isExpanded import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.isHidden import eu.kanade.tachiyomi.util.view.isHidden
import eu.kanade.tachiyomi.util.view.isVisible import eu.kanade.tachiyomi.util.view.isVisible
@ -86,18 +87,24 @@ import eu.kanade.tachiyomi.util.view.setStyle
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf import eu.kanade.tachiyomi.util.view.visibleIf
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.EndAnimatorListener import eu.kanade.tachiyomi.widget.EndAnimatorListener
import kotlinx.android.synthetic.main.filter_bottom_sheet.* import kotlinx.android.synthetic.main.filter_bottom_sheet.*
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.android.synthetic.main.library_grid_recycler.* import kotlinx.android.synthetic.main.library_grid_recycler.*
import kotlinx.android.synthetic.main.library_grid_recycler.recycler
import kotlinx.android.synthetic.main.library_list_controller.* import kotlinx.android.synthetic.main.library_list_controller.*
import kotlinx.android.synthetic.main.library_list_controller.shadow2
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.rounded_category_hopper.* import kotlinx.android.synthetic.main.rounded_category_hopper.*
import kotlinx.android.synthetic.main.source_controller.*
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.nextInt import kotlin.random.nextInt
@ -167,6 +174,7 @@ class LibraryController(
private var scrollDistance = 0f private var scrollDistance = 0f
private val scrollDistanceTilHidden = 1000.dpToPx private val scrollDistanceTilHidden = 1000.dpToPx
private var textAnim: ViewPropertyAnimator? = null private var textAnim: ViewPropertyAnimator? = null
var startingFiltersY = 0f
var hopperGravity: Int = preferences.hopperGravity().get() var hopperGravity: Int = preferences.hopperGravity().get()
set(value) { set(value) {
field = value field = value
@ -201,6 +209,7 @@ class LibraryController(
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
val recyclerCover = recycler_cover ?: return val recyclerCover = recycler_cover ?: return
val bottomBar = activity?.bottom_nav
if (!recyclerCover.isClickable && isAnimatingHopper != true) { if (!recyclerCover.isClickable && isAnimatingHopper != true) {
category_hopper_frame.translationY += dy category_hopper_frame.translationY += dy
category_hopper_frame.translationY = category_hopper_frame.translationY =
@ -222,6 +231,23 @@ class LibraryController(
showCategoryText(currentCategory.name) showCategoryText(currentCategory.name)
} }
} }
if (bottomBar != null) {
if (filter_bottom_sheet.sheetBehavior.isHidden()) {
val pad = bottomBar.translationY - bottomBar.height
filter_bottom_sheet.translationY = pad
} else {
filter_bottom_sheet.translationY = 0f
}
val pad = bottomBar.translationY - bottomBar.height
shadow2.translationY = pad
filter_bottom_sheet.updatePaddingRelative(
bottom = max(
(-bottomBar.translationY + bottomBar.height).toInt(),
view?.rootWindowInsets?.getBottomGestureInsets() ?: 0
)
)
filter_bottom_sheet.sheetBehavior?.peekHeight = 60.dpToPx + filter_bottom_sheet.paddingBottom
}
val savedCurrentCategory = getHeader(true)?.category ?: return val savedCurrentCategory = getHeader(true)?.category ?: return
if (savedCurrentCategory.order != lastUsedCategory) { if (savedCurrentCategory.order != lastUsedCategory) {
lastUsedCategory = savedCurrentCategory.order lastUsedCategory = savedCurrentCategory.order
@ -237,19 +263,21 @@ class LibraryController(
fast_scroller.showScrollbar() fast_scroller.showScrollbar()
} }
RecyclerView.SCROLL_STATE_IDLE -> { RecyclerView.SCROLL_STATE_IDLE -> {
updateHopperPosition()
}
}
}
}
fun updateHopperPosition(show: Boolean = false) {
val shortAnimationDuration = resources?.getInteger( val shortAnimationDuration = resources?.getInteger(
android.R.integer.config_shortAnimTime android.R.integer.config_shortAnimTime
) ?: 0 ) ?: 0
if (!recyclerCover.isClickable) {
category_hopper_frame.animate().translationY( category_hopper_frame.animate().translationY(
if (category_hopper_frame.translationY > 25f.dpToPx) 50f.dpToPx if (!show && category_hopper_frame.translationY > 25f.dpToPx) 50f.dpToPx
else 0f else 0f
).setDuration(shortAnimationDuration.toLong()).start() ).setDuration(shortAnimationDuration.toLong()).start()
} }
}
}
}
}
fun saveActiveCategory(category: Category) { fun saveActiveCategory(category: Category) {
activeCategory = category.order activeCategory = category.order
@ -322,7 +350,6 @@ class LibraryController(
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
if (!::presenter.isInitialized) presenter = LibraryPresenter(this) if (!::presenter.isInitialized) presenter = LibraryPresenter(this)
adapter = LibraryCategoryAdapter(this) adapter = LibraryCategoryAdapter(this)
@ -643,7 +670,9 @@ class LibraryController(
} }
private fun setRecyclerLayout() { private fun setRecyclerLayout() {
recycler.updatePaddingRelative(bottom = 50.dpToPx) recycler.post {
recycler.updatePaddingRelative(bottom = 50.dpToPx + (activity?.bottom_nav?.height ?: 0))
}
if (libraryLayout == 0) { if (libraryLayout == 0) {
recycler.spanCount = 1 recycler.spanCount = 1
recycler.updatePaddingRelative( recycler.updatePaddingRelative(
@ -668,7 +697,7 @@ class LibraryController(
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (type.isEnter) { if (type.isEnter) {
view?.applyWindowInsetsForRootController(activity!!.bottom_nav) filter_bottom_sheet.visible()
presenter.getLibrary() presenter.getLibrary()
DownloadService.callListeners() DownloadService.callListeners()
LibraryUpdateService.setListener(this) LibraryUpdateService.setListener(this)
@ -677,6 +706,9 @@ class LibraryController(
showDropdown() showDropdown()
} else { } else {
closeTip() closeTip()
if (filter_bottom_sheet.sheetBehavior.isHidden()) {
filter_bottom_sheet.invisible()
}
activity?.toolbar?.hideDropdown() activity?.toolbar?.hideDropdown()
} }
} }

View File

@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.ui.library.LibraryGroup import eu.kanade.tachiyomi.ui.library.LibraryGroup
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.collapse import eu.kanade.tachiyomi.util.view.collapse
@ -34,6 +35,7 @@ import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.* import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.android.synthetic.main.library_grid_recycler.* import kotlinx.android.synthetic.main.library_grid_recycler.*
import kotlinx.android.synthetic.main.library_list_controller.* import kotlinx.android.synthetic.main.library_list_controller.*
import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -94,6 +96,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
var onGroupClicked: (Int) -> Unit = { _ -> } var onGroupClicked: (Int) -> Unit = { _ -> }
var pager: View? = null var pager: View? = null
var controller: LibraryController? = null var controller: LibraryController? = null
var bottomBarHeight = 0
fun onCreate(controller: LibraryController) { fun onCreate(controller: LibraryController) {
clearButton = clear_button clearButton = clear_button
@ -102,6 +105,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
sheetBehavior?.isHideable = true sheetBehavior?.isHideable = true
this.controller = controller this.controller = controller
pager = controller.recycler pager = controller.recycler
pager?.post {
bottomBarHeight = (this@FilterBottomSheet.controller?.activity as? MainActivity)?.bottom_nav?.height ?: 0
}
val shadow2: View = controller.shadow2 val shadow2: View = controller.shadow2
val shadow: View = controller.shadow val shadow: View = controller.shadow
sheetBehavior?.addBottomSheetCallback( sheetBehavior?.addBottomSheetCallback(
@ -111,6 +117,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
shadow2.alpha = (1 - max(0f, progress)) * 0.25f shadow2.alpha = (1 - max(0f, progress)) * 0.25f
shadow.alpha = 1 + min(0f, progress) shadow.alpha = 1 + min(0f, progress)
updateRootPadding(progress) updateRootPadding(progress)
val bottomBar = (this@FilterBottomSheet.controller?.activity as? MainActivity)?.bottom_nav ?: return
val pad = bottomBar.translationY - bottomBar.height
translationY = pad * -min(0f, progress)
} }
override fun onStateChanged(p0: View, state: Int) { override fun onStateChanged(p0: View, state: Int) {
@ -183,7 +192,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
val shadow = controller?.shadow ?: return val shadow = controller?.shadow ?: return
if (state == BottomSheetBehavior.STATE_COLLAPSED) { if (state == BottomSheetBehavior.STATE_COLLAPSED) {
shadow.alpha = 1f shadow.alpha = 1f
pager?.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0 + 10.dpToPx) pager?.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0 + 10.dpToPx + bottomBarHeight)
} }
if (state == BottomSheetBehavior.STATE_EXPANDED) { if (state == BottomSheetBehavior.STATE_EXPANDED) {
pill.alpha = 0f pill.alpha = 0f
@ -192,7 +201,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
onGroupClicked(ACTION_HIDE_FILTER_TIP) onGroupClicked(ACTION_HIDE_FILTER_TIP)
reSortViews() reSortViews()
shadow.alpha = 0f shadow.alpha = 0f
pager?.updatePaddingRelative(bottom = 10.dpToPx) pager?.updatePaddingRelative(bottom = 10.dpToPx + bottomBarHeight)
} }
} }
@ -210,9 +219,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
val percent = (trueProgress * 100).roundToInt() val percent = (trueProgress * 100).roundToInt()
val value = (percent * (maxHeight - minHeight) / 100) + minHeight val value = (percent * (maxHeight - minHeight) / 100) + minHeight
if (trueProgress >= 0) if (trueProgress >= 0)
pager?.updatePaddingRelative(bottom = value + 10.dpToPx) pager?.updatePaddingRelative(bottom = value + 10.dpToPx + bottomBarHeight)
else else
pager?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt()) pager?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt() + bottomBarHeight)
} }
fun hasActiveFilters() = filterItems.any { it.isActivated } fun hasActiveFilters() = filterItems.any { it.isActivated }

View File

@ -238,6 +238,9 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
top = insets.systemWindowInsetTop top = insets.systemWindowInsetTop
) )
bottom_nav.updatePadding(bottom = insets.systemWindowInsetBottom) bottom_nav.updatePadding(bottom = insets.systemWindowInsetBottom)
bottom_view.updateLayoutParams<ViewGroup.LayoutParams> {
height = insets.systemWindowInsetBottom
}
} }
router = Conductor.attachRouter(this, container, savedInstanceState) router = Conductor.attachRouter(this, container, savedInstanceState)
@ -270,6 +273,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
syncActivityViewWithController(to, from, isPush) syncActivityViewWithController(to, from, isPush)
appbar.y = 0f appbar.y = 0f
bottom_nav.translationY = 0f
snackBar?.dismiss() snackBar?.dismiss()
} }
@ -281,6 +285,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
handler: ControllerChangeHandler handler: ControllerChangeHandler
) { ) {
appbar.y = 0f appbar.y = 0f
bottom_nav.translationY = 0f
showDLQueueTutorial() showDLQueueTutorial()
} }
} }

View File

@ -38,7 +38,6 @@ import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
import eu.kanade.tachiyomi.ui.recently_read.RemoveHistoryDialog import eu.kanade.tachiyomi.ui.recently_read.RemoveHistoryDialog
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
import eu.kanade.tachiyomi.util.view.expand import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.isExpanded import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.requestPermissionsSafe import eu.kanade.tachiyomi.util.view.requestPermissionsSafe
@ -103,7 +102,6 @@ class RecentsController(bundle: Bundle? = null) :
*/ */
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
// Initialize adapter // Initialize adapter
adapter = RecentMangaAdapter(this) adapter = RecentMangaAdapter(this)
recycler.adapter = adapter recycler.adapter = adapter
@ -127,6 +125,7 @@ class RecentsController(bundle: Bundle? = null) :
swipeRefreshLayout = swipe_refresh, swipeRefreshLayout = swipe_refresh,
afterInsets = { afterInsets = {
headerHeight = it.systemWindowInsetTop + appBarHeight headerHeight = it.systemWindowInsetTop + appBarHeight
recycler.updatePaddingRelative(bottom = activity!!.bottom_nav.height)
} }
) )
@ -432,7 +431,6 @@ class RecentsController(bundle: Bundle? = null) :
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (type.isEnter) { if (type.isEnter) {
view?.applyWindowInsetsForRootController(activity!!.bottom_nav)
if (type == ControllerChangeType.POP_ENTER) presenter.onCreate() if (type == ControllerChangeType.POP_ENTER) presenter.onCreate()
dl_bottom_sheet.dismiss() dl_bottom_sheet.dismiss()
} else { } else {

View File

@ -44,29 +44,6 @@ class SettingsGeneralController : SettingsController() {
} }
} }
intListPreference(activity) {
key = Keys.theme
titleRes = R.string.app_theme
entriesRes = arrayOf(
R.string.white_theme,
R.string.light_blue,
R.string.dark,
R.string.amoled_black,
R.string.dark_blue,
R.string.system_default,
R.string
.system_default_amoled,
R.string.system_default_all_blue
)
entryValues = listOf(1, 8, 2, 3, 4, 5, 6, 7)
defaultValue = 5
onChange {
activity?.recreate()
true
}
}
listPreference(activity) { listPreference(activity) {
key = Keys.dateFormat key = Keys.dateFormat
titleRes = R.string.date_format titleRes = R.string.date_format
@ -153,5 +130,39 @@ class SettingsGeneralController : SettingsController() {
} }
} }
} }
preferenceCategory {
titleRes = R.string.display
intListPreference(activity) {
key = Keys.theme
titleRes = R.string.app_theme
entriesRes = arrayOf(
R.string.white_theme,
R.string.light_blue,
R.string.dark,
R.string.amoled_black,
R.string.dark_blue,
R.string.system_default,
R.string
.system_default_amoled,
R.string.system_default_all_blue
)
entryValues = listOf(1, 8, 2, 3, 4, 5, 6, 7)
defaultValue = 5
onChange {
activity?.recreate()
true
}
}
switchPreference {
key = Keys.hideBottomNavOnScroll
titleRes = R.string.hide_bottom_nav
summaryRes = R.string.hides_on_scroll
defaultValue = true
}
}
} }
} }

View File

@ -10,6 +10,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.RecyclerView
import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.ControllerChangeType
import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.RouterTransaction
@ -32,7 +33,8 @@ import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController
import eu.kanade.tachiyomi.ui.source.latest.LatestUpdatesController import eu.kanade.tachiyomi.ui.source.latest.LatestUpdatesController
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController import eu.kanade.tachiyomi.util.system.getBottomGestureInsets
import eu.kanade.tachiyomi.util.system.spToPx
import eu.kanade.tachiyomi.util.view.collapse import eu.kanade.tachiyomi.util.view.collapse
import eu.kanade.tachiyomi.util.view.expand import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.isCollapsed import eu.kanade.tachiyomi.util.view.isCollapsed
@ -41,11 +43,17 @@ import eu.kanade.tachiyomi.util.view.requestPermissionsSafe
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.extensions_bottom_sheet.* import kotlinx.android.synthetic.main.extensions_bottom_sheet.*
import kotlinx.android.synthetic.main.extensions_bottom_sheet.sheet_layout
import kotlinx.android.synthetic.main.filter_bottom_sheet.*
import kotlinx.android.synthetic.main.library_list_controller.*
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.rounded_category_hopper.*
import kotlinx.android.synthetic.main.source_controller.* import kotlinx.android.synthetic.main.source_controller.*
import kotlinx.android.synthetic.main.source_controller.shadow2
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.math.max import kotlin.math.max
@ -112,7 +120,6 @@ class SourceController :
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
adapter = SourceAdapter(this) adapter = SourceAdapter(this)
@ -129,6 +136,19 @@ class SourceController :
recycler, recycler,
afterInsets = { afterInsets = {
headerHeight = it.systemWindowInsetTop + appBarHeight headerHeight = it.systemWindowInsetTop + appBarHeight
recycler.updatePaddingRelative(bottom = activity?.bottom_nav?.height ?: 0)
}
)
recycler?.post {
setBottomPadding()
}
recycler.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
setBottomPadding()
}
} }
) )
@ -154,6 +174,9 @@ class SourceController :
setTitle() setTitle()
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
} }
val bottomBar = activity?.bottom_nav ?: return
val pad = bottomBar.translationY - bottomBar.height
ext_bottom_sheet.updatePaddingRelative(bottom = (pad * (1 - max(progress, 0f))).toInt())
} }
override fun onStateChanged(p0: View, state: Int) { override fun onStateChanged(p0: View, state: Int) {
@ -187,6 +210,22 @@ class SourceController :
} }
} }
fun setBottomPadding() {
val bottomBar = activity?.bottom_nav ?: return
ext_bottom_sheet.updatePaddingRelative(
bottom =
if (ext_bottom_sheet.sheetBehavior.isExpanded()) 0 else
max(
(-bottomBar.translationY + bottomBar.height).toInt(),
this@SourceController.view?.rootWindowInsets?.getBottomGestureInsets()
?: 0
)
)
val pad = bottomBar.translationY - bottomBar.height
shadow2.translationY = pad
ext_bottom_sheet.sheetBehavior?.peekHeight = 48.spToPx + ext_bottom_sheet.paddingBottom
}
override fun showSheet() { override fun showSheet() {
ext_bottom_sheet.sheetBehavior?.expand() ext_bottom_sheet.sheetBehavior?.expand()
} }
@ -217,7 +256,6 @@ class SourceController :
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (!type.isPush && handler is SettingsSourcesFadeChangeHandler) { if (!type.isPush && handler is SettingsSourcesFadeChangeHandler) {
view?.applyWindowInsetsForRootController(activity!!.bottom_nav)
ext_bottom_sheet.updateExtTitle() ext_bottom_sheet.updateExtTitle()
ext_bottom_sheet.presenter.refreshExtensions() ext_bottom_sheet.presenter.refreshExtensions()
} }

View File

@ -128,6 +128,9 @@ val Int.pxToDp: Int
val Int.dpToPx: Int val Int.dpToPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt() get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.spToPx: Int
get() = (this * Resources.getSystem().displayMetrics.scaledDensity).toInt()
val Float.dpToPx: Float val Float.dpToPx: Float
get() = (this * Resources.getSystem().displayMetrics.density) get() = (this * Resources.getSystem().displayMetrics.density)

View File

@ -19,11 +19,14 @@ import com.bluelinelabs.conductor.ControllerChangeType
import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.main.BottomSheetController import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.abs import kotlin.math.abs
import kotlin.random.Random import kotlin.random.Random
@ -210,6 +213,8 @@ fun Controller.scrollViewWith(
) ?: 0 ) ?: 0
activity!!.appbar.animate().y(0f).setDuration(shortAnimationDuration.toLong()) activity!!.appbar.animate().y(0f).setDuration(shortAnimationDuration.toLong())
.start() .start()
activity!!.bottom_nav?.animate()?.translationYBy(0f)?.setDuration(shortAnimationDuration.toLong())
?.start()
lastY = 0f lastY = 0f
if (elevate) elevateFunc(false) if (elevate) elevateFunc(false)
} else { } else {
@ -219,14 +224,32 @@ fun Controller.scrollViewWith(
-activity!!.appbar.height.toFloat(), -activity!!.appbar.height.toFloat(),
0f 0f
) )
if (( val tabBar = activity!!.bottom_nav
if (tabBar != null && tabBar.isVisible()) {
val preferences: PreferencesHelper = Injekt.get()
if (preferences.hideBottomNavOnScroll().get()) {
tabBar.translationY += dy
tabBar.translationY = MathUtils.clamp(
tabBar.translationY,
0f,
tabBar.height.toFloat()
)
activity!!.bottom_view?.translationY = tabBar.translationY
} else if (tabBar.translationY != 0f) {
tabBar.translationY = 0f
activity!!.bottom_view?.translationY = 0f
}
}
if (!elevate && (
dy == 0 ||
( (
activity!!.appbar.y <= -activity!!.appbar.height.toFloat() || activity!!.appbar.y <= -activity!!.appbar.height.toFloat() ||
dy == 0 && activity!!.appbar.y == 0f dy == 0 && activity!!.appbar.y == 0f
) || dy == 0
) && !elevate
) )
)
) {
elevateFunc(true) elevateFunc(true)
}
lastY = activity!!.appbar.y lastY = activity!!.appbar.y
} }
} }

View File

@ -183,25 +183,6 @@ fun View.checkHeightThen(f: () -> Unit) {
) )
} }
fun View.applyWindowInsetsForRootController(bottomNav: View) {
viewTreeObserver.addOnGlobalLayoutListener(
object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (bottomNav.height > 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
setOnApplyWindowInsetsListener { view, insets ->
view.updateLayoutParams<FrameLayout.LayoutParams> {
bottomMargin = bottomNav.height
}
insets
}
requestApplyInsetsWhenAttached()
}
}
}
)
}
fun View.requestApplyInsetsWhenAttached() { fun View.requestApplyInsetsWhenAttached() {
if (isAttachedToWindow) { if (isAttachedToWindow) {
requestApplyInsets() requestApplyInsets()

View File

@ -62,6 +62,16 @@
</eu.kanade.tachiyomi.ui.base.CenteredToolbar> </eu.kanade.tachiyomi.ui.base.CenteredToolbar>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<View
android:id="@+id/bottom_view"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:ignore="KeyboardInaccessibleWidget" />
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav" android:id="@+id/bottom_nav"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -494,6 +494,8 @@
<string name="check_for_updates">Check for updates</string> <string name="check_for_updates">Check for updates</string>
<string name="auto_check_for_app_versions">Automatically check for new app versions</string> <string name="auto_check_for_app_versions">Automatically check for new app versions</string>
<string name="secure_screen">Secure screen</string> <string name="secure_screen">Secure screen</string>
<string name="hide_bottom_nav">Auto-Hide bottom navigation</string>
<string name="hides_on_scroll">Hides when scrolling</string>
<string name="hide_tachi_from_recents">Hide Tachiyomi from the recents screen</string> <string name="hide_tachi_from_recents">Hide Tachiyomi from the recents screen</string>
<string name="security">Security</string> <string name="security">Security</string>