Fixes for grid sizes on all device sizes

Catalouge grid now matches library grid type
This commit is contained in:
Jay 2020-04-07 22:32:28 -04:00
parent 839bfb8807
commit 26571a2508
7 changed files with 81 additions and 65 deletions

View File

@ -93,6 +93,7 @@ fun getRecentsQueryDistinct(search: String) = """
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = newest_chapter.${Chapter.COL_MANGA_ID} ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = newest_chapter.${Chapter.COL_MANGA_ID}
WHERE ${Manga.COL_FAVORITE} = 1 WHERE ${Manga.COL_FAVORITE} = 1
AND newest_chapter.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID} AND newest_chapter.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
AND ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED}
AND lower(${Manga.COL_TITLE}) LIKE '%$search%' AND lower(${Manga.COL_TITLE}) LIKE '%$search%'
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
LIMIT 8 LIMIT 8

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.catalogue.browse package eu.kanade.tachiyomi.ui.catalogue.browse
import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
@ -12,7 +11,6 @@ import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.f2prateek.rx.preferences.Preference
import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents
@ -22,6 +20,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
@ -109,11 +108,6 @@ open class BrowseCatalogueController(bundle: Bundle) :
*/ */
private var searchViewSubscription: Subscription? = null private var searchViewSubscription: Subscription? = null
/**
* Subscription for the number of manga per row.
*/
private var numColumnsSubscription: Subscription? = null
/** /**
* Endless loading item. * Endless loading item.
*/ */
@ -150,8 +144,6 @@ open class BrowseCatalogueController(bundle: Bundle) :
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
numColumnsSubscription?.unsubscribe()
numColumnsSubscription = null
searchViewSubscription?.unsubscribe() searchViewSubscription?.unsubscribe()
searchViewSubscription = null searchViewSubscription = null
adapter = null adapter = null
@ -161,8 +153,6 @@ open class BrowseCatalogueController(bundle: Bundle) :
} }
private fun setupRecycler(view: View) { private fun setupRecycler(view: View) {
numColumnsSubscription?.unsubscribe()
var oldPosition = RecyclerView.NO_POSITION var oldPosition = RecyclerView.NO_POSITION
val oldRecycler = catalogue_view?.getChildAt(1) val oldRecycler = catalogue_view?.getChildAt(1)
if (oldRecycler is RecyclerView) { if (oldRecycler is RecyclerView) {
@ -181,11 +171,11 @@ open class BrowseCatalogueController(bundle: Bundle) :
} }
} else { } else {
(catalogue_view.inflate(R.layout.catalogue_recycler_autofit) as AutofitRecyclerView).apply { (catalogue_view.inflate(R.layout.catalogue_recycler_autofit) as AutofitRecyclerView).apply {
numColumnsSubscription = getColumnsPreferenceForCurrentOrientation().asObservable() columnWidth = when (preferences.gridSize().getOrDefault()) {
.doOnNext { spanCount = it } 0 -> 1f
.skip(1) 2 -> 1.66f
// Set again the adapter to recalculate the covers height else -> 1.25f
.subscribe { adapter = this@BrowseCatalogueController.adapter } }
(layoutManager as androidx.recyclerview.widget.GridLayoutManager).spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() { (layoutManager as androidx.recyclerview.widget.GridLayoutManager).spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int { override fun getSpanSize(position: Int): Int {
@ -458,18 +448,6 @@ open class BrowseCatalogueController(bundle: Bundle) :
} }
} }
/**
* Returns a preference for the number of manga per row based on the current orientation.
*
* @return the preference.
*/
fun getColumnsPreferenceForCurrentOrientation(): Preference<Int> {
return if (resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT)
preferences.portraitColumns()
else
preferences.landscapeColumns()
}
/** /**
* Returns the view holder for the given manga. * Returns the view holder for the given manga.
* *

View File

@ -149,6 +149,7 @@ open class BrowseCataloguePresenter(
val sourceId = source.id val sourceId = source.id
val catalogueAsList = prefs.catalogueAsList() val catalogueAsList = prefs.catalogueAsList()
val catalougeListType = prefs.libraryLayout()
// Prepare the pager. // Prepare the pager.
pagerSubscription?.let { remove(it) } pagerSubscription?.let { remove(it) }
@ -156,7 +157,7 @@ open class BrowseCataloguePresenter(
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.map { it.first to it.second.map { networkToLocalManga(it, sourceId) } } .map { it.first to it.second.map { networkToLocalManga(it, sourceId) } }
.doOnNext { initializeMangas(it.second) } .doOnNext { initializeMangas(it.second) }
.map { it.first to it.second.map { CatalogueItem(it, catalogueAsList) } } .map { it.first to it.second.map { CatalogueItem(it, catalogueAsList, catalougeListType) } }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeReplay({ view, (page, mangas) -> .subscribeReplay({ view, (page, mangas) ->
view.onAddPage(page, mangas) view.onAddPage(page, mangas)

View File

@ -10,6 +10,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.ui.library.LibraryCategoryAdapter import eu.kanade.tachiyomi.ui.library.LibraryCategoryAdapter
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.widget.StateImageViewTarget import eu.kanade.tachiyomi.widget.StateImageViewTarget
import kotlinx.android.synthetic.main.catalogue_grid_item.* import kotlinx.android.synthetic.main.catalogue_grid_item.*
import kotlinx.android.synthetic.main.unread_download_badge.* import kotlinx.android.synthetic.main.unread_download_badge.*
@ -25,9 +26,18 @@ import kotlinx.android.synthetic.main.unread_download_badge.*
*/ */
class CatalogueGridHolder( class CatalogueGridHolder(
private val view: View, private val view: View,
private val adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>> private val adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
) : compact: Boolean
CatalogueHolder(view, adapter) { ) : CatalogueHolder(view, adapter) {
init {
if (compact) {
text_layout.gone()
} else {
compact_title.gone()
gradient.gone()
}
}
/** /**
* Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this * Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this
@ -37,7 +47,8 @@ class CatalogueGridHolder(
*/ */
override fun onSetValues(manga: Manga) { override fun onSetValues(manga: Manga) {
// Update the title of the manga. // Update the title of the manga.
compact_title.text = manga.title title.text = manga.title
compact_title.text = title.text
badge_view.setInLibrary(manga.favorite) badge_view.setInLibrary(manga.favorite)
// Update the cover. // Update the cover.

View File

@ -1,10 +1,12 @@
package eu.kanade.tachiyomi.ui.catalogue.browse package eu.kanade.tachiyomi.ui.catalogue.browse
import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.f2prateek.rx.preferences.Preference import com.f2prateek.rx.preferences.Preference
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -14,11 +16,15 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.catalogue_grid_item.view.* import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
class CatalogueItem(val manga: Manga, private val catalogueAsList: Preference<Boolean>) : class CatalogueItem(
val manga: Manga,
private val catalogueAsList: Preference<Boolean>,
private val catalogueListType: Preference<Int>
) :
AbstractFlexibleItem<CatalogueHolder>() { AbstractFlexibleItem<CatalogueHolder>() {
override fun getLayoutRes(): Int { override fun getLayoutRes(): Int {
@ -31,19 +37,36 @@ class CatalogueItem(val manga: Manga, private val catalogueAsList: Preference<Bo
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): CatalogueHolder { override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): CatalogueHolder {
val parent = adapter.recyclerView val parent = adapter.recyclerView
return if (parent is AutofitRecyclerView) { return if (parent is AutofitRecyclerView) {
val listType = catalogueListType.getOrDefault()
view.apply { view.apply {
val coverHeight = (parent.itemWidth / 3 * 4f).toInt() val coverHeight = (parent.itemWidth / 3 * 4f).toInt()
constraint_layout.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, if (listType == 1) {
WRAP_CONTENT) gradient.layoutParams = FrameLayout.LayoutParams(
val marginParams = card.layoutParams as ConstraintLayout.LayoutParams FrameLayout.LayoutParams.MATCH_PARENT,
marginParams.bottomMargin = 10.dpToPx (coverHeight * 0.66f).toInt(),
card.layoutParams = marginParams Gravity.BOTTOM)
text_layout.gone() card.updateLayoutParams<ConstraintLayout.LayoutParams> {
constraint_layout.minHeight = 0 bottomMargin = 6.dpToPx
cover_thumbnail.adjustViewBounds = false
cover_thumbnail.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight)
} }
CatalogueGridHolder(view, adapter) } else {
constraint_layout.background = ContextCompat.getDrawable(
context, R.drawable.library_item_selector
)
}
constraint_layout.layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
)
cover_thumbnail.maxHeight = Int.MAX_VALUE
cover_thumbnail.minimumHeight = 0
constraint_layout.minHeight = 0
cover_thumbnail.scaleType = ImageView.ScaleType.CENTER_CROP
cover_thumbnail.adjustViewBounds = false
cover_thumbnail.layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
(parent.itemWidth / 3f * 3.7f).toInt()
)
}
CatalogueGridHolder(view, adapter, listType == 1)
} else { } else {
CatalogueListHolder(view, adapter) CatalogueListHolder(view, adapter)
} }

View File

@ -378,11 +378,14 @@ class LibraryController(
if (libraryLayout == 0) { if (libraryLayout == 0) {
recycler.spanCount = 1 recycler.spanCount = 1
recycler.updatePaddingRelative( recycler.updatePaddingRelative(
start = 0, start = 0, end = 0
end = 0
) )
} else { } else {
recycler.columnWidth = (90 + (preferences.gridSize().getOrDefault() * 30)).dpToPx recycler.columnWidth = when (preferences.gridSize().getOrDefault()) {
0 -> 1f
2 -> 1.66f
else -> 1.25f
}
recycler.updatePaddingRelative( recycler.updatePaddingRelative(
start = (if (alwaysShowScroller) 2 else 5).dpToPx, start = (if (alwaysShowScroller) 2 else 5).dpToPx,
end = (if (alwaysShowScroller) 12 else 5).dpToPx end = (if (alwaysShowScroller) 12 else 5).dpToPx

View File

@ -3,21 +3,20 @@ package eu.kanade.tachiyomi.widget
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import eu.kanade.tachiyomi.util.system.pxToDp
import kotlin.math.max import kotlin.math.max
import kotlin.math.roundToInt
class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
androidx.recyclerview.widget.RecyclerView(context, attrs) { androidx.recyclerview.widget.RecyclerView(context, attrs) {
val manager = GridLayoutManager(context, 1) val manager = GridLayoutManager(context, 1)
var columnWidth = -1 var columnWidth = -1f
set(value) { set(value) {
field = value field = value
if (value > 0 && measuredWidth > 0) { if (measuredWidth > 0)
val count = max(1, measuredWidth / value) setSpan(true)
spanCount = count
// manager.spanCount = count
}
} }
var spanCount = 0 var spanCount = 0
@ -35,28 +34,28 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att
} }
init { init {
if (attrs != null) {
val attrsArray = intArrayOf(android.R.attr.columnWidth)
val array = context.obtainStyledAttributes(attrs, attrsArray)
columnWidth = array.getDimensionPixelSize(0, -1)
array.recycle()
}
layoutManager = manager layoutManager = manager
} }
private fun getTempSpan(): Int { private fun getTempSpan(): Int {
if (spanCount == 0 && columnWidth > 0) { if (spanCount == 0 && columnWidth > 0) {
return max(1, measuredWidth / columnWidth) val dpWidth = (measuredWidth.pxToDp / 100f).roundToInt()
return max(1, (dpWidth / columnWidth).roundToInt())
} }
return 2 return 3
} }
override fun onMeasure(widthSpec: Int, heightSpec: Int) { override fun onMeasure(widthSpec: Int, heightSpec: Int) {
super.onMeasure(widthSpec, heightSpec) super.onMeasure(widthSpec, heightSpec)
if (spanCount == 0 && columnWidth > 0) { setSpan()
val count = max(1, measuredWidth / columnWidth) }
private fun setSpan(force: Boolean = false) {
if ((spanCount == 0 || force) && columnWidth > 0) {
val dpWidth = (measuredWidth.pxToDp / 100f).roundToInt()
val count = max(1, (dpWidth / columnWidth).roundToInt())
spanCount = count spanCount = count
// Timber.d("Dp width: $dpWidth - RSpan: $spanCount")
} }
} }
} }