mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-10 23:47:48 +01:00
Rewrite catalogue adapter
This commit is contained in:
parent
f86c3c81bf
commit
871e17c2f5
12 changed files with 207 additions and 213 deletions
|
@ -1,107 +0,0 @@
|
|||
package eu.kanade.tachiyomi.ui.catalogue
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.widget.FrameLayout
|
||||
import eu.davidea.flexibleadapter4.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.util.inflate
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Adapter storing a list of manga from the catalogue.
|
||||
*
|
||||
* @param fragment the fragment containing this adapter.
|
||||
*/
|
||||
class CatalogueAdapter(val fragment: CatalogueFragment) : FlexibleAdapter<CatalogueHolder, Manga>() {
|
||||
|
||||
/**
|
||||
* Property to get the list of manga in the adapter.
|
||||
*/
|
||||
val items: List<Manga>
|
||||
get() = mItems
|
||||
|
||||
init {
|
||||
mItems = ArrayList()
|
||||
setHasStableIds(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a list of manga to the adapter.
|
||||
*
|
||||
* @param list the list to add.
|
||||
*/
|
||||
fun addItems(list: List<Manga>) {
|
||||
if (list.isNotEmpty()) {
|
||||
val sizeBeforeAdding = mItems.size
|
||||
mItems.addAll(list)
|
||||
notifyItemRangeInserted(sizeBeforeAdding, list.size)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the list of manga from the adapter.
|
||||
*/
|
||||
fun clear() {
|
||||
val sizeBeforeRemoving = mItems.size
|
||||
mItems.clear()
|
||||
notifyItemRangeRemoved(0, sizeBeforeRemoving)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier for a manga.
|
||||
*
|
||||
* @param position the position in the adapter.
|
||||
* @return an identifier for the item.
|
||||
*/
|
||||
override fun getItemId(position: Int): Long {
|
||||
return mItems[position].id!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to filter the list. Required but not used.
|
||||
*/
|
||||
override fun updateDataSet(param: String) {}
|
||||
|
||||
/**
|
||||
* Creates a new view holder.
|
||||
*
|
||||
* @param parent the parent view.
|
||||
* @param viewType the type of the holder.
|
||||
* @return a new view holder for a manga.
|
||||
*/
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CatalogueHolder {
|
||||
if (parent.id == R.id.catalogue_grid) {
|
||||
val view = parent.inflate(R.layout.item_catalogue_grid).apply {
|
||||
card.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight)
|
||||
gradient.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM)
|
||||
}
|
||||
return CatalogueGridHolder(view, this, fragment)
|
||||
} else {
|
||||
val view = parent.inflate(R.layout.item_catalogue_list)
|
||||
return CatalogueListHolder(view, this, fragment)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a holder with a new position.
|
||||
*
|
||||
* @param holder the holder to bind.
|
||||
* @param position the position to bind.
|
||||
*/
|
||||
override fun onBindViewHolder(holder: CatalogueHolder, position: Int) {
|
||||
val manga = getItem(position)
|
||||
holder.onSetValues(manga)
|
||||
}
|
||||
|
||||
/**
|
||||
* Property to return the height for the covers based on the width to keep an aspect ratio.
|
||||
*/
|
||||
val coverHeight: Int
|
||||
get() = (fragment.recycler as AutofitRecyclerView).itemWidth / 3 * 4
|
||||
|
||||
}
|
|
@ -11,11 +11,12 @@ import android.widget.ProgressBar
|
|||
import android.widget.Spinner
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.f2prateek.rx.preferences.Preference
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.data.source.online.LoginSource
|
||||
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaActivity
|
||||
|
@ -24,7 +25,6 @@ import eu.kanade.tachiyomi.util.inflate
|
|||
import eu.kanade.tachiyomi.util.snack
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import eu.kanade.tachiyomi.widget.EndlessScrollListener
|
||||
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_catalogue.*
|
||||
|
@ -40,7 +40,10 @@ import java.util.concurrent.TimeUnit.MILLISECONDS
|
|||
* Uses R.layout.fragment_catalogue.
|
||||
*/
|
||||
@RequiresPresenter(CataloguePresenter::class)
|
||||
open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleViewHolder.OnListItemClickListener {
|
||||
open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(),
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
FlexibleAdapter.EndlessScrollListener<ProgressItem> {
|
||||
|
||||
/**
|
||||
* Spinner shown in the toolbar to change the selected source.
|
||||
|
@ -50,12 +53,7 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
/**
|
||||
* Adapter containing the list of manga from the catalogue.
|
||||
*/
|
||||
private lateinit var adapter: CatalogueAdapter
|
||||
|
||||
/**
|
||||
* Scroll listener. It loads next pages when the end of the list is reached.
|
||||
*/
|
||||
private var scrollListener: EndlessScrollListener? = null
|
||||
private lateinit var adapter: FlexibleAdapter<IFlexible<*>>
|
||||
|
||||
/**
|
||||
* Query of the search box.
|
||||
|
@ -130,6 +128,8 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
|
||||
lateinit var recycler: RecyclerView
|
||||
|
||||
private var progressItem: ProgressItem? = null
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates a new instance of this fragment.
|
||||
|
@ -160,7 +160,7 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
}
|
||||
|
||||
// Initialize adapter, scroll listener and recycler views
|
||||
adapter = CatalogueAdapter(this)
|
||||
adapter = FlexibleAdapter(null, this)
|
||||
setupRecycler()
|
||||
|
||||
// Create toolbar spinner
|
||||
|
@ -251,11 +251,18 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
.skip(1)
|
||||
// Set again the adapter to recalculate the covers height
|
||||
.subscribe { adapter = this@CatalogueFragment.adapter }
|
||||
|
||||
(layoutManager as GridLayoutManager).spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return when (adapter.getItemViewType(position)) {
|
||||
R.layout.item_catalogue_grid -> 1
|
||||
else -> spanCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scrollListener = EndlessScrollListener(recycler.layoutManager as LinearLayoutManager, { requestNextPage() })
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.addOnScrollListener(scrollListener)
|
||||
recycler.adapter = adapter
|
||||
|
||||
catalogue_view.addView(recycler, 1)
|
||||
|
@ -376,29 +383,19 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
presenter.restartPager(newQuery)
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the next page (if available). Called from scroll listeners when they reach the end.
|
||||
*/
|
||||
private fun requestNextPage() {
|
||||
if (presenter.hasNextPage()) {
|
||||
showGridProgressBar()
|
||||
presenter.requestNext()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when the network request is received.
|
||||
*
|
||||
* @param page the current page.
|
||||
* @param mangas the list of manga of the page.
|
||||
*/
|
||||
fun onAddPage(page: Int, mangas: List<Manga>) {
|
||||
fun onAddPage(page: Int, mangas: List<CatalogueItem>) {
|
||||
hideProgressBar()
|
||||
if (page == 1) {
|
||||
adapter.clear()
|
||||
scrollListener?.resetScroll()
|
||||
resetProgressItem()
|
||||
}
|
||||
adapter.addItems(mangas)
|
||||
adapter.onLoadMoreComplete(mangas)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -407,6 +404,7 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
* @param error the error received.
|
||||
*/
|
||||
fun onAddPageError(error: Throwable) {
|
||||
adapter.onLoadMoreComplete(null)
|
||||
hideProgressBar()
|
||||
|
||||
val message = if (error is NoResultsException) "No results found" else (error.message ?: "")
|
||||
|
@ -414,12 +412,42 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
snack?.dismiss()
|
||||
snack = catalogue_view.snack(message, Snackbar.LENGTH_INDEFINITE) {
|
||||
setAction(R.string.action_retry) {
|
||||
showProgressBar()
|
||||
// If not the first page, show bottom progress bar.
|
||||
if (adapter.mainItemCount > 0) {
|
||||
val item = progressItem ?: return@setAction
|
||||
adapter.addScrollableFooterWithDelay(item, 0, true)
|
||||
} else {
|
||||
showProgressBar()
|
||||
}
|
||||
presenter.requestNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new progress item and reenables the scroll listener.
|
||||
*/
|
||||
private fun resetProgressItem() {
|
||||
progressItem = ProgressItem()
|
||||
adapter.endlessTargetCount = 0
|
||||
adapter.setEndlessScrollListener(this, progressItem!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the adapter when scrolled near the bottom.
|
||||
*/
|
||||
override fun onLoadMore(lastPosition: Int, currentPage: Int) {
|
||||
if (presenter.hasNextPage()) {
|
||||
presenter.requestNext()
|
||||
} else {
|
||||
adapter.onLoadMoreComplete(null)
|
||||
adapter.endlessTargetCount = 1
|
||||
}
|
||||
}
|
||||
|
||||
override fun noMoreLoad(newItemsSize: Int) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when a manga is initialized.
|
||||
*
|
||||
|
@ -433,13 +461,18 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
* Swaps the current display mode.
|
||||
*/
|
||||
fun swapDisplayMode() {
|
||||
if (!isAdded) return
|
||||
|
||||
presenter.swapDisplayMode()
|
||||
val isListMode = presenter.isListMode
|
||||
activity.invalidateOptionsMenu()
|
||||
setupRecycler()
|
||||
if (!isListMode || !context.connectivityManager.isActiveNetworkMetered) {
|
||||
// Initialize mangas if going to grid view or if over wifi when going to list view
|
||||
presenter.initializeMangas(adapter.items)
|
||||
val mangas = (0..adapter.itemCount-1).mapNotNull {
|
||||
(adapter.getItem(it) as? CatalogueItem)?.manga
|
||||
}
|
||||
presenter.initializeMangas(mangas)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,21 +507,11 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
snack = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the progress bar at the end of the screen.
|
||||
*/
|
||||
private fun showGridProgressBar() {
|
||||
progress_grid.visibility = ProgressBar.VISIBLE
|
||||
snack?.dismiss()
|
||||
snack = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides active progress bars.
|
||||
*/
|
||||
private fun hideProgressBar() {
|
||||
progress.visibility = ProgressBar.GONE
|
||||
progress_grid.visibility = ProgressBar.GONE
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -497,10 +520,10 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
* @param position the position of the element clicked.
|
||||
* @return true if the item should be selected, false otherwise.
|
||||
*/
|
||||
override fun onListItemClick(position: Int): Boolean {
|
||||
val item = adapter.getItem(position) ?: return false
|
||||
override fun onItemClick(position: Int): Boolean {
|
||||
val item = adapter.getItem(position) as? CatalogueItem ?: return false
|
||||
|
||||
val intent = MangaActivity.newIntent(activity, item, true)
|
||||
val intent = MangaActivity.newIntent(activity, item.manga, true)
|
||||
startActivity(intent)
|
||||
return false
|
||||
}
|
||||
|
@ -510,8 +533,8 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
|||
*
|
||||
* @param position the position of the element clicked.
|
||||
*/
|
||||
override fun onListItemLongClick(position: Int) {
|
||||
val manga = adapter.getItem(position) ?: return
|
||||
override fun onItemLongClick(position: Int) {
|
||||
val manga = (adapter.getItem(position) as? CatalogueItem?)?.manga ?: return
|
||||
|
||||
val textRes = if (manga.favorite) R.string.remove_from_library else R.string.add_to_library
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.catalogue
|
|||
import android.view.View
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
|
||||
|
||||
|
@ -12,11 +13,10 @@ import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
|
|||
*
|
||||
* @param view the inflated view for this holder.
|
||||
* @param adapter the adapter handling this holder.
|
||||
* @param listener a listener to react to single tap and long tap events.
|
||||
* @constructor creates a new catalogue holder.
|
||||
*/
|
||||
class CatalogueGridHolder(private val view: View, private val adapter: CatalogueAdapter, listener: OnListItemClickListener) :
|
||||
CatalogueHolder(view, adapter, listener) {
|
||||
class CatalogueGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) :
|
||||
CatalogueHolder(view, adapter) {
|
||||
|
||||
/**
|
||||
* Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
package eu.kanade.tachiyomi.ui.catalogue
|
||||
|
||||
import android.view.View
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
|
||||
|
||||
/**
|
||||
* Generic class used to hold the displayed data of a manga in the catalogue.
|
||||
*
|
||||
* @param view the inflated view for this holder.
|
||||
* @param adapter the adapter handling this holder.
|
||||
* @param listener a listener to react to single tap and long tap events.
|
||||
*/
|
||||
abstract class CatalogueHolder(view: View, adapter: CatalogueAdapter, listener: OnListItemClickListener) :
|
||||
FlexibleViewHolder(view, adapter, listener) {
|
||||
abstract class CatalogueHolder(view: View, adapter: FlexibleAdapter<*>) :
|
||||
FlexibleViewHolder(view, adapter) {
|
||||
|
||||
/**
|
||||
* Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package eu.kanade.tachiyomi.ui.catalogue
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.util.inflate
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
|
||||
|
||||
class CatalogueItem(val manga: Manga) : AbstractFlexibleItem<CatalogueHolder>() {
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.item_catalogue_grid
|
||||
}
|
||||
|
||||
override fun createViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, inflater: LayoutInflater, parent: ViewGroup): CatalogueHolder {
|
||||
if (parent is AutofitRecyclerView) {
|
||||
val view = parent.inflate(R.layout.item_catalogue_grid).apply {
|
||||
card.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, parent.itemWidth / 3 * 4)
|
||||
gradient.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, parent.itemWidth / 3 * 4 / 2, Gravity.BOTTOM)
|
||||
}
|
||||
return CatalogueGridHolder(view, adapter)
|
||||
} else {
|
||||
val view = parent.inflate(R.layout.item_catalogue_list)
|
||||
return CatalogueListHolder(view, adapter)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: CatalogueHolder, position: Int, payloads: List<Any?>?) {
|
||||
holder.onSetValues(manga)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other is CatalogueItem) {
|
||||
return manga.id!! == other.manga.id!!
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return manga.id!!.hashCode()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.catalogue
|
|||
import android.view.View
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.util.getResourceColor
|
||||
import kotlinx.android.synthetic.main.item_catalogue_list.view.*
|
||||
|
@ -13,11 +14,10 @@ import kotlinx.android.synthetic.main.item_catalogue_list.view.*
|
|||
*
|
||||
* @param view the inflated view for this holder.
|
||||
* @param adapter the adapter handling this holder.
|
||||
* @param listener a listener to react to single tap and long tap events.
|
||||
* @constructor creates a new catalogue holder.
|
||||
*/
|
||||
class CatalogueListHolder(private val view: View, adapter: CatalogueAdapter, listener: OnListItemClickListener) :
|
||||
CatalogueHolder(view, adapter, listener) {
|
||||
class CatalogueListHolder(private val view: View, adapter: FlexibleAdapter<*>) :
|
||||
CatalogueHolder(view, adapter) {
|
||||
|
||||
private val favoriteColor = view.context.getResourceColor(android.R.attr.textColorHint)
|
||||
private val unfavoriteColor = view.context.getResourceColor(android.R.attr.textColorPrimary)
|
||||
|
|
|
@ -163,6 +163,7 @@ open class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
|||
.observeOn(Schedulers.io())
|
||||
.map { it.first to it.second.map { networkToLocalManga(it, sourceId) } }
|
||||
.doOnNext { initializeMangas(it.second) }
|
||||
.map { it.first to it.second.map(::CatalogueItem) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeReplay({ view, pair ->
|
||||
view.onAddPage(pair.first, pair.second)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package eu.kanade.tachiyomi.ui.catalogue
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
|
||||
class ProgressItem : AbstractFlexibleItem<ProgressItem.Holder>() {
|
||||
|
||||
var loadMore = true
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.progress_item
|
||||
}
|
||||
|
||||
override fun createViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, inflater: LayoutInflater, parent: ViewGroup): Holder {
|
||||
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: Holder, position: Int, payloads: List<Any?>) {
|
||||
holder.progressBar.visibility = View.GONE
|
||||
holder.progressMessage.visibility = View.GONE
|
||||
|
||||
if (!adapter.isEndlessScrollEnabled) {
|
||||
loadMore = false
|
||||
}
|
||||
|
||||
if (loadMore) {
|
||||
holder.progressBar.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.progressMessage.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return this === other
|
||||
}
|
||||
|
||||
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
|
||||
|
||||
val progressBar = view.findViewById(R.id.progress_bar) as ProgressBar
|
||||
val progressMessage = view.findViewById(R.id.progress_message) as TextView
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package eu.kanade.tachiyomi.widget
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
|
||||
class EndlessScrollListener(
|
||||
private val layoutManager: LinearLayoutManager,
|
||||
private val requestNext: () -> Unit)
|
||||
: RecyclerView.OnScrollListener() {
|
||||
|
||||
companion object {
|
||||
// The minimum amount of items to have below your current scroll position before loading
|
||||
// more.
|
||||
private val VISIBLE_THRESHOLD = 5
|
||||
}
|
||||
|
||||
private var previousTotal = 0 // The total number of items in the dataset after the last load
|
||||
private var loading = true // True if we are still waiting for the last set of data to load.
|
||||
private var firstVisibleItem = 0
|
||||
private var visibleItemCount = 0
|
||||
private var totalItemCount = 0
|
||||
|
||||
fun resetScroll() {
|
||||
previousTotal = 0
|
||||
loading = true
|
||||
}
|
||||
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
visibleItemCount = recyclerView.childCount
|
||||
totalItemCount = layoutManager.itemCount
|
||||
firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
|
||||
|
||||
if (loading && totalItemCount > previousTotal) {
|
||||
loading = false
|
||||
previousTotal = totalItemCount
|
||||
}
|
||||
if (!loading && totalItemCount - visibleItemCount <= firstVisibleItem + VISIBLE_THRESHOLD) {
|
||||
// End has been reached
|
||||
requestNext()
|
||||
loading = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -21,14 +21,6 @@
|
|||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_grid"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
25
app/src/main/res/layout/progress_item.xml
Normal file
25
app/src/main/res/layout/progress_item.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:padding="8dp">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/progress_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_more_results"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</FrameLayout>
|
|
@ -223,6 +223,7 @@
|
|||
<string name="source_requires_login">This source requires you to log in</string>
|
||||
<string name="select_source">Select a source</string>
|
||||
<string name="no_valid_sources">Please enable at least one valid source</string>
|
||||
<string name="no_more_results">No more results</string>
|
||||
|
||||
<!-- Manga activity -->
|
||||
<string name="manga_not_in_db">This manga was removed from the database!</string>
|
||||
|
|
Loading…
Reference in a new issue