Pin navigation ui option #851

master
Koitharu 2 years ago
parent 3affec0f88
commit 19da2267d6
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -74,6 +74,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
val isNavLabelsVisible: Boolean val isNavLabelsVisible: Boolean
get() = prefs.getBoolean(KEY_NAV_LABELS, true) get() = prefs.getBoolean(KEY_NAV_LABELS, true)
val isNavBarPinned: Boolean
get() = prefs.getBoolean(KEY_NAV_PINNED, false)
var gridSize: Int var gridSize: Int
get() = prefs.getInt(KEY_GRID_SIZE, 100) get() = prefs.getInt(KEY_GRID_SIZE, 100)
set(value) = prefs.edit { putInt(KEY_GRID_SIZE, value) } set(value) = prefs.edit { putInt(KEY_GRID_SIZE, value) }
@ -653,6 +656,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
const val KEY_RELATED_MANGA = "related_manga" const val KEY_RELATED_MANGA = "related_manga"
const val KEY_NAV_MAIN = "nav_main" const val KEY_NAV_MAIN = "nav_main"
const val KEY_NAV_LABELS = "nav_labels" const val KEY_NAV_LABELS = "nav_labels"
const val KEY_NAV_PINNED = "nav_pinned"
const val KEY_32BIT_COLOR = "enhanced_colors" const val KEY_32BIT_COLOR = "enhanced_colors"
const val KEY_SOURCES_ORDER = "sources_sort_order" const val KEY_SOURCES_ORDER = "sources_sort_order"
const val KEY_SOURCES_CATALOG = "sources_catalog" const val KEY_SOURCES_CATALOG = "sources_catalog"

@ -25,6 +25,15 @@ class HideBottomNavigationOnScrollBehavior @JvmOverloads constructor(
private var dyRatio = 1F private var dyRatio = 1F
var isPinned: Boolean = false
set(value) {
field = value
if (value) {
offsetAnimator?.cancel()
offsetAnimator = null
}
}
override fun layoutDependsOn(parent: CoordinatorLayout, child: BottomNavigationView, dependency: View): Boolean { override fun layoutDependsOn(parent: CoordinatorLayout, child: BottomNavigationView, dependency: View): Boolean {
return dependency is AppBarLayout return dependency is AppBarLayout
} }
@ -51,7 +60,7 @@ class HideBottomNavigationOnScrollBehavior @JvmOverloads constructor(
axes: Int, axes: Int,
type: Int, type: Int,
): Boolean { ): Boolean {
if (axes != ViewCompat.SCROLL_AXIS_VERTICAL) { if (isPinned || axes != ViewCompat.SCROLL_AXIS_VERTICAL) {
return false return false
} }
lastStartedType = type lastStartedType = type
@ -69,7 +78,9 @@ class HideBottomNavigationOnScrollBehavior @JvmOverloads constructor(
type: Int, type: Int,
) { ) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type) super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
child.translationY = (child.translationY + (dy * dyRatio)).coerceIn(0F, child.height.toFloat()) if (!isPinned) {
child.translationY = (child.translationY + (dy * dyRatio)).coerceIn(0F, child.height.toFloat())
}
} }
override fun onStopNestedScroll( override fun onStopNestedScroll(
@ -78,7 +89,7 @@ class HideBottomNavigationOnScrollBehavior @JvmOverloads constructor(
target: View, target: View,
type: Int, type: Int,
) { ) {
if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) { if (!isPinned && (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH)) {
animateBottomNavigationVisibility(child, child.translationY < child.height / 2) animateBottomNavigationVisibility(child, child.translationY < child.height / 2)
} }
} }

@ -38,6 +38,15 @@ class SlidingBottomNavigationView @JvmOverloads constructor(
private var currentState = STATE_UP private var currentState = STATE_UP
private var behavior = HideBottomNavigationOnScrollBehavior() private var behavior = HideBottomNavigationOnScrollBehavior()
var isPinned: Boolean
get() = behavior.isPinned
set(value) {
behavior.isPinned = value
if (value) {
translationX = 0f
}
}
override fun getBehavior(): CoordinatorLayout.Behavior<*> { override fun getBehavior(): CoordinatorLayout.Behavior<*> {
return behavior return behavior
} }

@ -13,6 +13,7 @@ import androidx.appcompat.view.ActionMode
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.children
import androidx.core.view.inputmethod.EditorInfoCompat import androidx.core.view.inputmethod.EditorInfoCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -131,6 +132,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
viewModel.onFirstStart.observeEvent(this) { viewModel.onFirstStart.observeEvent(this) {
WelcomeSheet.show(supportFragmentManager) WelcomeSheet.show(supportFragmentManager)
} }
viewModel.isBottomNavPinned.observe(this, ::setNavbarPinned)
searchSuggestionViewModel.isIncognitoModeEnabled.observe(this, this::onIncognitoModeChanged) searchSuggestionViewModel.isIncognitoModeEnabled.observe(this, this::onIncognitoModeChanged)
} }
@ -399,6 +401,22 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
} }
} }
private fun setNavbarPinned(isPinned: Boolean) {
viewBinding.bottomNav?.isPinned = isPinned
for (view in viewBinding.appbar.children) {
val lp = view.layoutParams as? AppBarLayout.LayoutParams ?: continue
val scrollFlags = if (isPinned) {
lp.scrollFlags and SCROLL_FLAG_SCROLL.inv()
} else {
lp.scrollFlags or SCROLL_FLAG_SCROLL
}
if (scrollFlags != lp.scrollFlags) {
lp.scrollFlags = scrollFlags
view.layoutParams = lp
}
}
}
private inner class CloseSearchCallback : OnBackPressedCallback(false) { private inner class CloseSearchCallback : OnBackPressedCallback(false) {
override fun handleOnBackPressed() { override fun handleOnBackPressed() {

@ -4,11 +4,13 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus import kotlinx.coroutines.plus
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.github.AppUpdateRepository
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.observeAsFlow
import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.call
@ -46,6 +48,12 @@ class MainViewModel @Inject constructor(
.withErrorHandling() .withErrorHandling()
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, 0) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, 0)
val isBottomNavPinned = settings.observeAsFlow(
AppSettings.KEY_NAV_PINNED,
) {
isNavBarPinned
}.flowOn(Dispatchers.Default)
init { init {
launchJob { launchJob {
appUpdateRepository.fetchUpdate() appUpdateRepository.fetchUpdate()

@ -19,7 +19,7 @@
android:orientation="vertical" android:orientation="vertical"
android:paddingVertical="@dimen/list_spacing_normal" android:paddingVertical="@dimen/list_spacing_normal"
app:bubbleSize="small" app:bubbleSize="small"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager=".core.ui.list.FitHeightLinearLayoutManager"
tools:listitem="@layout/item_feed" /> tools:listitem="@layout/item_feed" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

@ -634,4 +634,6 @@
<string name="more_frequently">More frequently</string> <string name="more_frequently">More frequently</string>
<string name="frequency_of_check">Frequency of check</string> <string name="frequency_of_check">Frequency of check</string>
<string name="new_chapters_pattern">%1$s: %2$d</string> <string name="new_chapters_pattern">%1$s: %2$d</string>
<string name="pin_navigation_ui">Pin navigation UI</string>
<string name="pin_navigation_ui_summary">Do not hide navgation bar and search view on scroll</string>
</resources> </resources>

@ -76,6 +76,12 @@
android:key="nav_labels" android:key="nav_labels"
android:title="@string/show_labels_in_navbar" /> android:title="@string/show_labels_in_navbar" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="nav_pinned"
android:summary="@string/pin_navigation_ui_summary"
android:title="@string/pin_navigation_ui" />
<org.koitharu.kotatsu.settings.utils.ActivityListPreference <org.koitharu.kotatsu.settings.utils.ActivityListPreference
android:key="app_locale" android:key="app_locale"
android:title="@string/language" /> android:title="@string/language" />

Loading…
Cancel
Save