From 0de3558ab3d96e9aa38c77d78b78e0870c0b64bf Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 4 Sep 2021 11:58:44 -0400 Subject: [PATCH] Retain scroll position when selecting app theme preference Co-authored-by: Jays2Kings --- .../setting/SettingsAppearanceController.kt | 25 +++++++++++- .../widget/preference/ThemesPreference.kt | 40 +++++++++++++++---- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt index 534d7646cf..2b5ea060ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt @@ -1,6 +1,8 @@ package eu.kanade.tachiyomi.ui.setting import android.os.Build +import android.os.Bundle +import android.view.View import androidx.core.app.ActivityCompat import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R @@ -23,6 +25,8 @@ import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values class SettingsAppearanceController : SettingsController() { + private var themesPreference: ThemesPreference? = null + override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_appearance @@ -59,7 +63,7 @@ class SettingsAppearanceController : SettingsController() { summary = "%s" } - initThenAdd(ThemesPreference(context)) { + themesPreference = initThenAdd(ThemesPreference(context)) { key = Keys.appTheme titleRes = R.string.pref_app_theme @@ -158,4 +162,23 @@ class SettingsAppearanceController : SettingsController() { } } } + + override fun onSaveViewState(view: View, outState: Bundle) { + themesPreference?.let { + outState.putInt(THEMES_SCROLL_POSITION, it.lastScrollPosition ?: 0) + } + super.onSaveInstanceState(outState) + } + + override fun onRestoreViewState(view: View, savedViewState: Bundle) { + super.onRestoreViewState(view, savedViewState) + themesPreference?.lastScrollPosition = savedViewState.getInt(THEMES_SCROLL_POSITION, 0) + } + + override fun onDestroyView(view: View) { + super.onDestroyView(view) + themesPreference = null + } } + +private const val THEMES_SCROLL_POSITION = "themesScrollPosition" diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreference.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreference.kt index 8543cc7310..1eb5dcd989 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreference.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreference.kt @@ -8,13 +8,23 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferenceValues +import eu.kanade.tachiyomi.util.system.dpToPx class ThemesPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : ListPreference(context, attrs), ThemesPreferenceAdapter.OnItemClickListener { + private var recycler: RecyclerView? = null private val adapter = ThemesPreferenceAdapter(this) + var lastScrollPosition: Int? = null + + var entries: List = emptyList() + set(value) { + field = value + adapter.setItems(value) + } + init { layoutResource = R.layout.pref_themes_list } @@ -22,9 +32,18 @@ class ThemesPreference @JvmOverloads constructor(context: Context, attrs: Attrib override fun onBindViewHolder(holder: PreferenceViewHolder) { super.onBindViewHolder(holder) - val themesList = holder.findViewById(R.id.themes_list) as RecyclerView - themesList.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) - themesList.adapter = adapter + recycler = holder.findViewById(R.id.themes_list) as RecyclerView + recycler?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) + recycler?.adapter = adapter + + // Retain scroll position on activity recreate after changing theme + recycler?.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + lastScrollPosition = recyclerView.computeHorizontalScrollOffset() + } + }) + lastScrollPosition?.let { scrollToOffset(it) } } override fun onItemClick(position: Int) { @@ -36,9 +55,16 @@ class ThemesPreference @JvmOverloads constructor(context: Context, attrs: Attrib // no-op; not actually a DialogPreference } - var entries: List = emptyList() - set(value) { - field = value - adapter.setItems(value) + private fun scrollToOffset(lX: Int) { + recycler?.let { + (it.layoutManager as LinearLayoutManager).apply { + scrollToPositionWithOffset( + // 118dp is the width of the pref_theme_item layout + lX / 118.dpToPx, + -lX % 118.dpToPx + ) + } + lastScrollPosition = it.computeHorizontalScrollOffset() } + } }