From 9f974c9401430dc35c61349da5a951067fd1c612 Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 24 Apr 2020 18:15:37 -0400 Subject: [PATCH] Refactor library sheet into tabs --- .../tachiyomi/ui/library/LibraryController.kt | 8 +- .../ui/library/LibrarySettingsSheet.kt | 188 +++++++++++------- .../tachiyomi/ui/reader/ReaderPageSheet.kt | 3 - .../tachiyomi/widget/MaxHeightViewPager.kt | 30 +++ .../res/layout/library_settings_sheet.xml | 21 ++ 5 files changed, 166 insertions(+), 84 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/MaxHeightViewPager.kt create mode 100644 app/src/main/res/layout/library_settings_sheet.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 8bcd079658..bb8da54a1a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -166,10 +166,10 @@ class LibraryController( settingsSheet = LibrarySettingsSheet(activity!!) { group -> when (group) { - is LibrarySettingsSheet.Settings.FilterGroup -> onFilterChanged() - is LibrarySettingsSheet.Settings.SortGroup -> onSortChanged() - is LibrarySettingsSheet.Settings.DisplayGroup -> reattachAdapter() - is LibrarySettingsSheet.Settings.BadgeGroup -> onDownloadBadgeChanged() + is LibrarySettingsSheet.FilterSettings.FilterGroup -> onFilterChanged() + is LibrarySettingsSheet.SortSettings.SortGroup -> onSortChanged() + is LibrarySettingsSheet.DisplaySettings.DisplayGroup -> reattachAdapter() + is LibrarySettingsSheet.DisplaySettings.BadgeGroup -> onDownloadBadgeChanged() } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt index f121066786..a033d355cc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt @@ -3,78 +3,73 @@ package eu.kanade.tachiyomi.ui.library import android.app.Activity import android.content.Context import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup import com.google.android.material.bottomsheet.BottomSheetDialog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.databinding.LibrarySettingsSheetBinding import eu.kanade.tachiyomi.widget.ExtendedNavigationView +import eu.kanade.tachiyomi.widget.ViewPagerAdapter import uy.kohesive.injekt.injectLazy class LibrarySettingsSheet( - activity: Activity, - onGroupClickListener: (ExtendedNavigationView.Group) -> Unit + private val activity: Activity, + private val onGroupClickListener: (ExtendedNavigationView.Group) -> Unit ) : BottomSheetDialog(activity) { - private var navView: Settings + private val filterSettings = FilterSettings(activity) + private val tabItems = listOf( + Pair(R.string.action_filter, filterSettings), + Pair(R.string.action_sort, SortSettings(activity)), + Pair(R.string.action_display, DisplaySettings(activity)) + ) init { - navView = Settings(activity) - navView.onGroupClicked = onGroupClickListener + val binding: LibrarySettingsSheetBinding = LibrarySettingsSheetBinding.inflate(activity.layoutInflater) - setContentView(navView) + val adapter = LibrarySettingsSheetAdapter() + binding.librarySettingsPager.adapter = adapter + binding.librarySettingsTabs.setupWithViewPager(binding.librarySettingsPager) + + setContentView(binding.root) } fun hasActiveFilters(): Boolean { - return navView.hasActiveFilters() + return filterSettings.hasActiveFilters() } - /** - * The navigation view shown in the sheet with the different options to show the library. - */ - class Settings @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : - ExtendedNavigationView(context, attrs) { + private inner class LibrarySettingsSheetAdapter : ViewPagerAdapter() { - private val preferences: PreferencesHelper by injectLazy() + override fun createView(container: ViewGroup, position: Int): View { + val view = tabItems[position].second + view.onGroupClicked = onGroupClickListener + return view + } - /** - * List of groups shown in the view. - */ - private val groups = listOf(FilterGroup(), SortGroup(), DisplayGroup(), BadgeGroup()) + override fun getCount(): Int { + return tabItems.size + } - /** - * Adapter instance. - */ - private val adapter = Adapter(groups.map { it.createItems() }.flatten()) + override fun getPageTitle(position: Int): CharSequence { + return activity.resources!!.getString(tabItems[position].first) + } + } - /** - * Click listener to notify the parent fragment when an item from a group is clicked. - */ - var onGroupClicked: (Group) -> Unit = {} + inner class FilterSettings @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + Settings(context, attrs) { + + private val filterGroup = FilterGroup() init { - recycler.adapter = adapter - addView(recycler) - - groups.forEach { it.initModels() } + addGroups(listOf(filterGroup)) } /** * Returns true if there's at least one filter from [FilterGroup] active. */ fun hasActiveFilters(): Boolean { - return (groups[0] as FilterGroup).items.any { it.checked } - } - - /** - * Adapter of the recycler view. - */ - inner class Adapter(items: List) : ExtendedNavigationView.Adapter(items) { - - override fun onItemClicked(item: Item) { - if (item is GroupedItem) { - item.group.onItemClicked(item) - onGroupClicked(item.group) - } - } + return filterGroup.items.any { it.checked } } /** @@ -83,16 +78,12 @@ class LibrarySettingsSheet( inner class FilterGroup : Group { private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this) - private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this) - private val completed = Item.CheckboxGroup(R.string.completed, this) + override val header = null override val items = listOf(downloaded, unread, completed) - - override val header = Item.Header(R.string.action_filter) - - override val footer = Item.Separator() + override val footer = null override fun initModels() { downloaded.checked = preferences.downloadedOnly().get() || preferences.filterDownloaded().get() @@ -113,6 +104,14 @@ class LibrarySettingsSheet( adapter.notifyItemChanged(item) } } + } + + inner class SortSettings @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + Settings(context, attrs) { + + init { + addGroups(listOf(SortGroup())) + } /** * Sorting group (alphabetically, by last read, ...) and ascending or descending. @@ -120,23 +119,16 @@ class LibrarySettingsSheet( inner class SortGroup : Group { private val alphabetically = Item.MultiSort(R.string.action_sort_alpha, this) - private val total = Item.MultiSort(R.string.action_sort_total, this) - private val lastRead = Item.MultiSort(R.string.action_sort_last_read, this) - private val lastChecked = Item.MultiSort(R.string.action_sort_last_checked, this) - private val unread = Item.MultiSort(R.string.action_filter_unread, this) - private val latestChapter = Item.MultiSort(R.string.action_sort_latest_chapter, this) + override val header = null override val items = listOf(alphabetically, lastRead, lastChecked, unread, total, latestChapter) - - override val header = Item.Header(R.string.action_sort) - - override val footer = Item.Separator() + override val footer = null override fun initModels() { val sorting = preferences.librarySortingMode().get() @@ -187,23 +179,13 @@ class LibrarySettingsSheet( item.group.items.forEach { adapter.notifyItemChanged(it) } } } + } - inner class BadgeGroup : Group { - private val downloadBadge = - Item.CheckboxGroup(R.string.action_display_download_badge, this) - override val header = null - override val footer = null - override val items = listOf(downloadBadge) - override fun initModels() { - downloadBadge.checked = preferences.downloadBadge().get() - } + inner class DisplaySettings @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + Settings(context, attrs) { - override fun onItemClicked(item: Item) { - item as Item.CheckboxGroup - item.checked = !item.checked - preferences.downloadBadge().set((item.checked)) - adapter.notifyItemChanged(item) - } + init { + addGroups(listOf(DisplayGroup(), BadgeGroup())) } /** @@ -212,13 +194,10 @@ class LibrarySettingsSheet( inner class DisplayGroup : Group { private val grid = Item.Radio(R.string.action_display_grid, this) - private val list = Item.Radio(R.string.action_display_list, this) + override val header = null override val items = listOf(grid, list) - - override val header = Item.Header(R.string.action_display) - override val footer = null override fun initModels() { @@ -239,5 +218,60 @@ class LibrarySettingsSheet( item.group.items.forEach { adapter.notifyItemChanged(it) } } } + + inner class BadgeGroup : Group { + private val downloadBadge = Item.CheckboxGroup(R.string.action_display_download_badge, this) + + override val header = null + override val items = listOf(downloadBadge) + override val footer = null + + override fun initModels() { + downloadBadge.checked = preferences.downloadBadge().get() + } + + override fun onItemClicked(item: Item) { + item as Item.CheckboxGroup + item.checked = !item.checked + preferences.downloadBadge().set((item.checked)) + adapter.notifyItemChanged(item) + } + } + } + + open inner class Settings(context: Context, attrs: AttributeSet?) : + ExtendedNavigationView(context, attrs) { + + val preferences: PreferencesHelper by injectLazy() + lateinit var adapter: Adapter + + /** + * Click listener to notify the parent fragment when an item from a group is clicked. + */ + var onGroupClicked: (Group) -> Unit = {} + + init { + addView(recycler) + } + + fun addGroups(groups: List) { + adapter = Adapter(groups.map { it.createItems() }.flatten()) + recycler.adapter = adapter + + groups.forEach { it.initModels() } + } + + /** + * Adapter of the recycler view. + */ + inner class Adapter(items: List) : ExtendedNavigationView.Adapter(items) { + + override fun onItemClicked(item: Item) { + if (item is GroupedItem) { + item.group.onItemClicked(item) + onGroupClicked(item.group) + } + } + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt index 1e98cbccd7..3fcffb17f2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt @@ -19,9 +19,6 @@ class ReaderPageSheet( private val page: ReaderPage ) : BottomSheetDialog(activity) { - /** - * View used on this sheet. - */ private val view = activity.layoutInflater.inflate(R.layout.reader_page_sheet, null) init { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/MaxHeightViewPager.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/MaxHeightViewPager.kt new file mode 100644 index 0000000000..05c9a426fc --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/MaxHeightViewPager.kt @@ -0,0 +1,30 @@ +package eu.kanade.tachiyomi.widget + +import android.content.Context +import android.util.AttributeSet +import androidx.viewpager.widget.ViewPager + +/** + * A [ViewPager] that sets its height to the maximum height of its children. + * This is a way to mimic WRAP_CONTENT for its height. + */ +class MaxHeightViewPager(context: Context, attrs: AttributeSet?) : ViewPager(context, attrs) { + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + var measuredHeight = heightMeasureSpec + + var height = 0 + for (i in 0 until childCount) { + val child = getChildAt(i) + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)) + val h = child.measuredHeight + if (h > height) height = h + } + + if (height != 0) { + measuredHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) + } + + super.onMeasure(widthMeasureSpec, measuredHeight) + } +} diff --git a/app/src/main/res/layout/library_settings_sheet.xml b/app/src/main/res/layout/library_settings_sheet.xml new file mode 100644 index 0000000000..16d83527aa --- /dev/null +++ b/app/src/main/res/layout/library_settings_sheet.xml @@ -0,0 +1,21 @@ + + + + + + + +