Separated library display options in *tabs*

To all my fellow tab-hating fans: I'm so sorry. Words cannot express the disappointment in myself. I shall be posting a public YouTube apology video soon.
This commit is contained in:
Jays2Kings 2021-03-22 22:10:40 -04:00
parent 791b94e7a3
commit 90a6543334
20 changed files with 571 additions and 419 deletions

View File

@ -1,158 +0,0 @@
package eu.kanade.tachiyomi.ui.library
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.RadioButton
import android.widget.RadioGroup
import com.f2prateek.rx.preferences.Preference
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.setting.SettingsLibraryController
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.isCollapsed
import eu.kanade.tachiyomi.util.view.setBottomEdge
import eu.kanade.tachiyomi.util.view.setEdgeToEdge
import eu.kanade.tachiyomi.util.view.visibleIf
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.android.synthetic.main.display_bottom_sheet.*
import uy.kohesive.injekt.injectLazy
class DisplayBottomSheet(private val controller: LibraryController) : BottomSheetDialog
(controller.activity!!, R.style.BottomSheetDialogTheme) {
val activity = controller.activity!!
/**
* Preferences helper.
*/
private val preferences by injectLazy<PreferencesHelper>()
private var sheetBehavior: BottomSheetBehavior<*>
init {
// Use activity theme for this layout
val view = activity.layoutInflater.inflate(R.layout.display_bottom_sheet, null)
setContentView(view)
sheetBehavior = BottomSheetBehavior.from(view.parent as ViewGroup)
setEdgeToEdge(activity, view)
val height = activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
sheetBehavior.peekHeight = 220.dpToPx + height
sheetBehavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, progress: Float) { }
override fun onStateChanged(p0: View, state: Int) {
if (state == BottomSheetBehavior.STATE_EXPANDED) {
sheetBehavior.skipCollapsed = true
}
}
}
)
}
override fun onStart() {
super.onStart()
sheetBehavior.skipCollapsed = true
sheetBehavior.expand()
}
/**
* Called when the sheet is created. It initializes the listeners and values of the preferences.
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initGeneralPreferences()
setBottomEdge(display_layout, activity)
close_button.setOnClickListener { dismiss() }
settings_scroll_view.viewTreeObserver.addOnGlobalLayoutListener {
val isScrollable =
settings_scroll_view!!.height < display_layout.height +
settings_scroll_view.paddingTop + settings_scroll_view.paddingBottom
close_button.visibleIf(isScrollable)
}
}
private fun initGeneralPreferences() {
display_group.bindToPreference(preferences.libraryLayout()) {
controller.reattachAdapter()
if (sheetBehavior.isCollapsed()) dismiss()
}
show_all.bindToPreference(preferences.showAllCategories()) {
controller.presenter.getLibrary()
category_show.isEnabled = it
}
category_show.isEnabled = show_all.isChecked
category_show.bindToPreference(preferences.showCategoryInTitle()) {
controller.showMiniBar()
}
hide_hopper.bindToPreference(preferences.hideHopper()) {
controller.hideHopper(it)
}
uniform_grid.bindToPreference(preferences.uniformGrid()) {
controller.reattachAdapter()
}
grid_size_toggle_group.bindToPreference(preferences.gridSize()) {
controller.reattachAdapter()
}
download_badge.bindToPreference(preferences.downloadBadge()) {
controller.presenter.requestDownloadBadgesUpdate()
}
unread_badge_group.bindToPreference(preferences.unreadBadgeType()) {
controller.presenter.requestUnreadBadgesUpdate()
}
hide_reading.bindToPreference(preferences.hideStartReadingButton()) {
controller.reattachAdapter()
}
hide_filters.bindToPreference(preferences.hideFiltersAtStart())
more_settings.setOnClickListener {
controller.router.pushController(SettingsLibraryController().withFadeTransaction())
dismiss()
}
}
/**
* Binds a checkbox or switch view with a boolean preference.
*/
private fun CompoundButton.bindToPreference(pref: Preference<Boolean>, block: (() -> Unit)? = null) {
isChecked = pref.getOrDefault()
setOnCheckedChangeListener { _, isChecked ->
pref.set(isChecked)
block?.invoke()
}
}
/**
* Binds a checkbox or switch view with a boolean preference.
*/
private fun CompoundButton.bindToPreference(
pref: com.tfcporciuncula.flow
.Preference<Boolean>,
block: ((Boolean) -> Unit)? = null
) {
isChecked = pref.get()
setOnCheckedChangeListener { _, isChecked ->
pref.set(isChecked)
block?.invoke(isChecked)
}
}
/**
* Binds a radio group with a int preference.
*/
private fun RadioGroup.bindToPreference(pref: Preference<Int>, block: (() -> Unit)? = null) {
(getChildAt(pref.getOrDefault()) as RadioButton).isChecked = true
setOnCheckedChangeListener { _, checkedId ->
val index = indexOfChild(findViewById(checkedId))
pref.set(index)
block?.invoke()
}
}
}

View File

@ -60,6 +60,7 @@ import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_STATUS
import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_TAG
import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_TRACK_STATUS
import eu.kanade.tachiyomi.ui.library.LibraryGroup.UNGROUPED
import eu.kanade.tachiyomi.ui.library.display.TabbedLibraryDisplaySheet
import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet
import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.MainActivity
@ -485,7 +486,7 @@ class LibraryController(
FilterBottomSheet.ACTION_REFRESH -> onRefresh()
FilterBottomSheet.ACTION_FILTER -> onFilterChanged()
FilterBottomSheet.ACTION_HIDE_FILTER_TIP -> showFilterTip()
FilterBottomSheet.ACTION_DISPLAY -> DisplayBottomSheet(this).show()
FilterBottomSheet.ACTION_DISPLAY -> TabbedLibraryDisplaySheet(this).show()
FilterBottomSheet.ACTION_EXPAND_COLLAPSE_ALL -> presenter.toggleAllCategoryVisibility()
FilterBottomSheet.ACTION_GROUP_BY -> {
val groupItems = mutableListOf(BY_DEFAULT, BY_TAG, BY_SOURCE, BY_STATUS)
@ -1287,7 +1288,7 @@ class LibraryController(
when {
filter_bottom_sheet.sheetBehavior.isHidden() -> filter_bottom_sheet.sheetBehavior?.collapse()
!filter_bottom_sheet.sheetBehavior.isExpanded() -> filter_bottom_sheet.sheetBehavior?.expand()
else -> DisplayBottomSheet(this).show()
else -> TabbedLibraryDisplaySheet(this).show()
}
}

View File

@ -0,0 +1,22 @@
package eu.kanade.tachiyomi.ui.library.display
import android.content.Context
import android.util.AttributeSet
import eu.kanade.tachiyomi.ui.library.LibraryController
import kotlinx.android.synthetic.main.library_badges_layout.view.*
class LibraryBadgesView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LibraryPreferenceView(context, attrs) {
override fun initGeneralPreferences() {
unread_badge_group.bindToPreference(preferences.unreadBadgeType()) {
controller.presenter.requestUnreadBadgesUpdate()
}
hide_reading.bindToPreference(preferences.hideStartReadingButton()) {
controller.reattachAdapter()
}
download_badge.bindToPreference(preferences.downloadBadge()) {
controller.presenter.requestDownloadBadgesUpdate()
}
}
}

View File

@ -0,0 +1,21 @@
package eu.kanade.tachiyomi.ui.library.display
import android.content.Context
import android.util.AttributeSet
import kotlinx.android.synthetic.main.library_display_layout.view.*
class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LibraryPreferenceView(context, attrs) {
override fun initGeneralPreferences() {
display_group.bindToPreference(preferences.libraryLayout()) {
controller.reattachAdapter()
}
uniform_grid.bindToPreference(preferences.uniformGrid()) {
controller.reattachAdapter()
}
grid_size_toggle_group.bindToPreference(preferences.gridSize()) {
controller.reattachAdapter()
}
}
}

View File

@ -0,0 +1,24 @@
package eu.kanade.tachiyomi.ui.library.display
import android.content.Context
import android.util.AttributeSet
import kotlinx.android.synthetic.main.library_other_layout.view.*
class LibraryOtherView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LibraryPreferenceView(context, attrs) {
override fun initGeneralPreferences() {
show_all.bindToPreference(preferences.showAllCategories()) {
controller.presenter.getLibrary()
category_show.isEnabled = it
}
category_show.isEnabled = show_all.isChecked
category_show.bindToPreference(preferences.showCategoryInTitle()) {
controller.showMiniBar()
}
hide_hopper.bindToPreference(preferences.hideHopper()) {
controller.hideHopper(it)
}
hide_filters.bindToPreference(preferences.hideFiltersAtStart())
}
}

View File

@ -0,0 +1,66 @@
package eu.kanade.tachiyomi.ui.library.display
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.widget.CompoundButton
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import com.f2prateek.rx.preferences.Preference
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.library.LibraryController
import uy.kohesive.injekt.injectLazy
abstract class LibraryPreferenceView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LinearLayout(context, attrs) {
internal val preferences by injectLazy<PreferencesHelper>()
lateinit var controller: LibraryController
abstract fun initGeneralPreferences()
override fun onFinishInflate() {
super.onFinishInflate()
initGeneralPreferences()
}
/**
* Binds a checkbox or switch view with a boolean preference.
*/
internal fun CompoundButton.bindToPreference(pref: Preference<Boolean>, block: (() -> Unit)? = null) {
isChecked = pref.getOrDefault()
setOnCheckedChangeListener { _, isChecked ->
pref.set(isChecked)
block?.invoke()
}
}
/**
* Binds a checkbox or switch view with a boolean preference.
*/
internal fun CompoundButton.bindToPreference(
pref: com.tfcporciuncula.flow
.Preference<Boolean>,
block: ((Boolean) -> Unit)? = null
) {
isChecked = pref.get()
setOnCheckedChangeListener { _, isChecked ->
pref.set(isChecked)
block?.invoke(isChecked)
}
}
/**
* Binds a radio group with a int preference.
*/
internal fun RadioGroup.bindToPreference(pref: Preference<Int>, block: (() -> Unit)? = null) {
(getChildAt(pref.getOrDefault()) as RadioButton).isChecked = true
setOnCheckedChangeListener { _, checkedId ->
val index = indexOfChild(findViewById(checkedId))
pref.set(index)
block?.invoke()
}
}
}

View File

@ -0,0 +1,50 @@
package eu.kanade.tachiyomi.ui.library.display
import android.view.View
import android.view.View.inflate
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.ui.setting.SettingsLibraryController
import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
open class TabbedLibraryDisplaySheet(controller: LibraryController):
TabbedBottomSheetDialog(controller) {
private val displayView: LibraryDisplayView = inflate(controller.activity!!, R.layout.library_display_layout, null) as LibraryDisplayView
private val badgesView: LibraryBadgesView = inflate(controller.activity!!, R.layout.library_badges_layout, null) as LibraryBadgesView
private val otherView: LibraryOtherView = inflate(controller.activity!!, R.layout.library_other_layout, null) as LibraryOtherView
init {
displayView.controller = controller
badgesView.controller = controller
otherView.controller = controller
menu.visible()
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
menu.tooltipText = context.getString(R.string.more_library_settings)
}
menu.setImageDrawable(ContextCompat.getDrawable(
context,
R.drawable.ic_settings_24dp
))
menu.setOnClickListener {
controller.router.pushController(SettingsLibraryController().withFadeTransaction())
dismiss()
}
}
override fun getTabViews(): List<View> = listOf(
displayView,
badgesView,
otherView
)
override fun getTabTitles(): List<Int> = listOf(
R.string.display,
R.string.badges,
R.string.other
)
}

View File

@ -5,6 +5,7 @@ import android.content.res.Configuration
import android.os.Parcelable
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.recyclerview.widget.LinearLayoutManager
@ -21,7 +22,10 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.ui.library.LibraryGroup
import eu.kanade.tachiyomi.ui.library.display.LibraryBadgesView
import eu.kanade.tachiyomi.ui.library.display.LibraryDisplayView
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.setting.SettingsLibraryController
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.collapse
@ -32,10 +36,13 @@ import eu.kanade.tachiyomi.util.view.isExpanded
import eu.kanade.tachiyomi.util.view.isHidden
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.visibleIf
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.android.synthetic.main.library_grid_recycler.*
import kotlinx.android.synthetic.main.library_list_controller.*
import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
import kotlinx.android.synthetic.main.track_item.*
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
@ -95,7 +102,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
var onGroupClicked: (Int) -> Unit = { _ -> }
var pager: View? = null
var libraryRecyler: View? = null
var controller: LibraryController? = null
var bottomBarHeight = 0
@ -105,8 +112,8 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
sheetBehavior = BottomSheetBehavior.from(this)
sheetBehavior?.isHideable = true
this.controller = controller
pager = controller.recycler
pager?.post {
libraryRecyler = controller.recycler
libraryRecyler?.post {
bottomBarHeight = (this@FilterBottomSheet.controller?.activity as? MainActivity)?.bottom_nav?.height ?: 0
}
val shadow2: View = controller.shadow2
@ -193,7 +200,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
val shadow = controller?.shadow ?: return
if (state == BottomSheetBehavior.STATE_COLLAPSED) {
shadow.alpha = 1f
pager?.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0 + 10.dpToPx + bottomBarHeight)
libraryRecyler?.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0 + 10.dpToPx + bottomBarHeight)
}
if (state == BottomSheetBehavior.STATE_EXPANDED) {
pill.alpha = 0f
@ -202,7 +209,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
onGroupClicked(ACTION_HIDE_FILTER_TIP)
reSortViews()
shadow.alpha = 0f
pager?.updatePaddingRelative(bottom = 10.dpToPx + bottomBarHeight)
libraryRecyler?.updatePaddingRelative(bottom = 10.dpToPx + bottomBarHeight)
}
}
@ -220,9 +227,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
val percent = (trueProgress * 100).roundToInt()
val value = (percent * (maxHeight - minHeight) / 100) + minHeight
if (trueProgress >= 0)
pager?.updatePaddingRelative(bottom = value + 10.dpToPx + bottomBarHeight)
libraryRecyler?.updatePaddingRelative(bottom = value + 10.dpToPx + bottomBarHeight)
else
pager?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt() + bottomBarHeight)
libraryRecyler?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt() + bottomBarHeight)
}
fun hasActiveFilters() = filterItems.any { it.isActivated }

View File

@ -0,0 +1,89 @@
package eu.kanade.tachiyomi.widget
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.viewpager.widget.ViewPager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.setEdgeToEdge
import kotlinx.android.synthetic.main.tabbed_bottom_sheet.*
abstract class TabbedBottomSheetDialog(private val controller: BaseController) :
BottomSheetDialog
(controller.activity!!, R.style.BottomSheetDialogTheme) {
private var sheetBehavior: BottomSheetBehavior<*>
val activity = controller.activity!!
init {
// Use activity theme for this layout
val view = activity.layoutInflater.inflate(R.layout.tabbed_bottom_sheet, null)
setContentView(view)
sheetBehavior = BottomSheetBehavior.from(view.parent as ViewGroup)
setEdgeToEdge(activity, view)
val height = activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
val adapter = TabbedSheetAdapter()
pager.offscreenPageLimit = 2
pager.adapter = adapter
tabs.setupWithViewPager(pager)
}
override fun onStart() {
super.onStart()
sheetBehavior.skipCollapsed = true
sheetBehavior.expand()
}
abstract fun getTabViews(): List<View>
abstract fun getTabTitles(): List<Int>
private inner class TabbedSheetAdapter : ViewPagerAdapter() {
override fun createView(container: ViewGroup, position: Int): View {
return getTabViews()[position]
}
override fun getCount(): Int {
return getTabViews().size
}
override fun getPageTitle(position: Int): CharSequence {
return activity.resources!!.getString(getTabTitles()[position])
}
}
}
class MeasuredViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): ViewPager(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var heightMeasureSpec = heightMeasureSpec
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
var height = 0
val childWidthSpec = MeasureSpec.makeMeasureSpec(
Math.max(
0, MeasureSpec.getSize(widthMeasureSpec) -
paddingLeft - paddingRight
),
MeasureSpec.getMode(widthMeasureSpec)
)
for (i in 0 until childCount) {
val child = getChildAt(i)
child.measure(childWidthSpec, MeasureSpec.UNSPECIFIED)
val h = child.measuredHeight
if (h > height) height = h
}
if (height != 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) + (rootWindowInsets?.systemWindowInsetBottom ?: 0)
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Based on mtrl_tabs_icon_color_selector_colored.
We want to use the accent color in some themes, but sometimes colorPrimary doesn't work well with
it (i.e. blue themes).
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorAccent" android:state_selected="true"/>
<item android:alpha="0.60" android:color="?attr/colorOnPrimary"/>
</selector>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Based on mtrl_tabs_icon_color_selector_colored.
Ensures visibility on top of the background color.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorAccent" android:state_selected="true"/>
<item android:alpha="0.60" android:color="?attr/colorOnBackground"/>
</selector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:topLeftRadius="4dp"
android:topRightRadius="4dp" />
<solid android:color="?attr/colorAccent" />
</shape>

View File

@ -1,247 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/display_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_rounded_background">
<androidx.core.widget.NestedScrollView
android:id="@+id/settings_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/display_layout"
style="@style/BottomSheetDialogTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical"
android:paddingTop="12dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="12dp"
android:text="@string/display" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioGroup
android:id="@+id/display_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/list" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/compact_grid" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/comfortable_grid" />
</RadioGroup>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/show_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/show_all_categories" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/category_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/always_show_current_category" />
</LinearLayout>
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:paddingStart="16dp"
android:paddingEnd="12dp"
android:text="@string/grid_options" />
<RadioGroup
android:id="@+id/grid_size_toggle_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:orientation="horizontal">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/x_small" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/small" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/medium" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/large" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/x_large" />
</RadioGroup>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/uniform_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/uniform_covers" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:paddingStart="16dp"
android:paddingEnd="12dp"
android:text="@string/unread_badges" />
<HorizontalScrollView
android:id="@+id/scroll_unread_view"
android:layout_width="match_parent"
android:requiresFadingEdge="horizontal"
android:scrollbars="none"
android:fadingEdgeLength="20dp"
android:layout_height="wrap_content">
<RadioGroup
android:id="@+id/unread_badge_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="@string/hide_badges" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:maxLines="2"
android:text="@string/show_badges" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:maxLines="2"
android:text="@string/show_count" />
</RadioGroup>
</HorizontalScrollView>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_reading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/hide_start_reading_button" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:paddingStart="16dp"
android:paddingEnd="12dp"
android:text="@string/more" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/download_badge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/download_badge" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_hopper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/hide_category_hopper" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_filters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/start_with_filters_hidden" />
<com.google.android.material.button.MaterialButton
android:id="@+id/more_settings"
style="@style/Theme.Widget.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/more_library_settings" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ImageView
android:id="@+id/close_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="end"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/round_ripple"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:src="@drawable/ic_close_24dp"
app:tint="@color/gray_button" />
</FrameLayout>

View File

@ -58,7 +58,7 @@
android:focusable="true"
android:padding="3dp"
android:src="@drawable/ic_close_24dp"
android:tint="@color/gray_button" />
app:tint="@color/gray_button" />
</LinearLayout>
</HorizontalScrollView>
@ -132,7 +132,7 @@
android:alpha="0.25"
android:contentDescription="@string/drag_handle"
android:src="@drawable/draggable_pill"
android:tint="?android:attr/textColorPrimary"
app:tint="?android:attr/textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.display.LibraryBadgesView
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/unread_badge_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="12dp"
android:paddingEnd="12dp">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="@string/hide_unread_badges" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="@string/show_unread_badges" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="@string/show_unread_count" />
</RadioGroup>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_reading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:text="@string/hide_start_reading_button" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/download_badge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/download_badge" />
</eu.kanade.tachiyomi.ui.library.display.LibraryBadgesView>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.display.LibraryDisplayView
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/display_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="12dp"
android:paddingEnd="12dp">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/list" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/compact_grid" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/comfortable_grid" />
</RadioGroup>
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingStart="16dp"
android:paddingEnd="12dp"
android:text="@string/grid_options" />
<RadioGroup
android:id="@+id/grid_size_toggle_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:orientation="horizontal">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/x_small" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/small" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/medium" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/large" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/x_large" />
</RadioGroup>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/uniform_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/uniform_covers" />
</eu.kanade.tachiyomi.ui.library.display.LibraryDisplayView>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.display.LibraryOtherView
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/category_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/always_show_current_category" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/show_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/show_all_categories" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_hopper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/hide_category_hopper" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_filters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/start_with_filters_hidden" />
</eu.kanade.tachiyomi.ui.library.display.LibraryOtherView>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tabs_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_rounded_background"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:id="@+id/tabs_constraint"
android:layout_height="wrap_content">
<!-- Remove background color so rounded sheet corners work -->
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
style="@style/Theme.Widget.Tabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/menu"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabTextColor="@color/tabs_selector_background"
app:tabIndicatorColor="?attr/colorAccent"
app:tabGravity="fill"
app:tabMode="fixed" />
<ImageButton
android:id="@+id/menu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/more"
android:paddingStart="10dp"
android:paddingEnd="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_settings_24dp"
app:tint="?attr/colorOnBackground" />
</androidx.constraintlayout.widget.ConstraintLayout>
<eu.kanade.tachiyomi.widget.MeasuredViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -148,6 +148,7 @@
<string name="download_badge">Download badges</string>
<string name="hide_start_reading_button">Hide start reading button</string>
<string name="unread_badges">Unread badges</string>
<string name="badges">Badges</string>
<string name="uniform_covers">Uniform covers</string>
<string name="x_small">XS</string>
<string name="small">S</string>
@ -155,9 +156,9 @@
<string name="large">L</string>
<string name="x_large">XL</string>
<string name="grid_options">Grid options</string>
<string name="hide_badges">Hide badges</string>
<string name="show_badges">Show badges</string>
<string name="show_count">Show count</string>
<string name="hide_unread_badges">Hide unread badges</string>
<string name="show_unread_badges">Show unread badges</string>
<string name="show_unread_count">Show unread count</string>
<string name="tap_library_to_show_filters">Tap the Library icon to show filters</string>
<string name="display_as">Display as</string>
<string name="hide_category_hopper">Hide category hopper</string>

View File

@ -104,6 +104,11 @@
<item name="android:textColor">?android:attr/textColorHint</item>
</style>
<style name="TextAppearance.Widget.Tab" parent="TextAppearance.MaterialComponents.Button">
<item name="android:textAllCaps">false</item>
<item name="android:letterSpacing">0</item>
</style>
<!--=======-->
<!--Widgets-->
<!--=======-->
@ -199,6 +204,22 @@
<item name="android:textColorHint">?android:attr/textColorHint</item>
</style>
<!--=================-->
<!--Widgets.TabLayout-->
<!--=================-->
<style name="Theme.Widget.Tabs" parent="Widget.MaterialComponents.TabLayout.Colored">
<item name="tabGravity">center</item>
<item name="tabIndicator">@drawable/tab_indicator</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabTextColor">@color/tabs_selector</item>
<item name="tabIndicatorFullWidth">false</item>
<item name="tabIndicatorHeight">3dp</item>
<item name="tabInlineLabel">true</item>
<item name="tabMinWidth">75dp</item>
<item name="tabMode">scrollable</item>
<item name="tabTextAppearance">@style/TextAppearance.Widget.Tab</item>
</style>
<!--==============-->
<!--Widgets.Button-->
<!--==============-->