From e95fcf61720906a88d784eba9a4d30d7f50a26b2 Mon Sep 17 00:00:00 2001 From: len Date: Sat, 30 Jul 2016 23:54:32 +0200 Subject: [PATCH] Dynamic recyclerview inflation for the library view and better swap handling --- .../tachiyomi/ui/library/LibraryAdapter.kt | 1 - .../ui/library/LibraryCategoryAdapter.kt | 17 ++-- .../ui/library/LibraryCategoryFragment.kt | 93 ++++--------------- .../tachiyomi/ui/library/LibraryFragment.kt | 73 +++++++++------ .../tachiyomi/ui/library/LibraryHolder.kt | 6 +- .../tachiyomi/ui/library/LibraryPresenter.kt | 17 +--- .../res/layout/fragment_library_category.xml | 30 +----- .../main/res/layout/library_grid_recycler.xml | 10 ++ .../main/res/layout/library_list_recycler.xml | 10 ++ 9 files changed, 99 insertions(+), 158 deletions(-) create mode 100644 app/src/main/res/layout/library_grid_recycler.xml create mode 100644 app/src/main/res/layout/library_list_recycler.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt index dcfc8539e..8cf6540d4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryAdapter.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.library import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager - import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.ui.base.adapter.SmartFragmentStatePagerAdapter diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index d814bbfe1..eb3c528da 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -8,7 +8,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.util.inflate -import kotlinx.android.synthetic.main.fragment_library_category.* +import eu.kanade.tachiyomi.widget.AutofitRecyclerView import kotlinx.android.synthetic.main.item_catalogue_grid.view.* import java.util.* @@ -85,15 +85,16 @@ class LibraryCategoryAdapter(val fragment: LibraryCategoryFragment) : */ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LibraryHolder { //depending on preferences, display a list or display a grid - if (parent.id == R.id.library_list) { - val view = parent.inflate(R.layout.item_library_list) - return LibraryListHolder(view, this, fragment) - } else { + if (parent is AutofitRecyclerView) { val view = parent.inflate(R.layout.item_catalogue_grid).apply { + val coverHeight = parent.itemWidth / 3 * 4 card.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight) gradient.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM) } return LibraryGridHolder(view, this, fragment) + } else { + val view = parent.inflate(R.layout.item_library_list) + return LibraryListHolder(view, this, fragment) } } @@ -112,10 +113,4 @@ class LibraryCategoryAdapter(val fragment: LibraryCategoryFragment) : holder.itemView.isActivated = isSelected(position) } - /** - * Property to return the height for the covers based on the width to keep an aspect ratio. - */ - val coverHeight: Int - get() = fragment.recycler.itemWidth / 3 * 4 - } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryFragment.kt index 826059805..084e1b135 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryFragment.kt @@ -1,24 +1,23 @@ package eu.kanade.tachiyomi.ui.library -import android.content.res.Configuration import android.os.Bundle -import android.support.v7.widget.GridLayoutManager import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.animation.AnimationUtils -import com.f2prateek.rx.preferences.Preference import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment import eu.kanade.tachiyomi.ui.manga.MangaActivity +import eu.kanade.tachiyomi.util.inflate import eu.kanade.tachiyomi.util.toast +import eu.kanade.tachiyomi.widget.AutofitRecyclerView import kotlinx.android.synthetic.main.fragment_library_category.* import rx.Subscription import uy.kohesive.injekt.injectLazy @@ -50,26 +49,11 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli */ private var libraryMangaSubscription: Subscription? = null - /** - * Subscription of the number of manga per row. - */ - private var numColumnsSubscription: Subscription? = null - - /** - * subscription to view toggle - */ - private var toggleViewSubscription: Subscription? = null - /** * Subscription of the library search. */ private var searchSubscription: Subscription? = null - /** - * display mode - */ - private var displayAsList: Boolean = false - companion object { /** * Key to save and restore [position] from a [Bundle]. @@ -97,45 +81,31 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli override fun onViewCreated(view: View, savedState: Bundle?) { adapter = LibraryCategoryAdapter(this) - //set up grid - recycler.setHasFixedSize(true) - (recycler.layoutManager as GridLayoutManager).recycleChildrenOnDetach = true - recycler.recycledViewPool = libraryFragment.pool - recycler.adapter = adapter + val recycler = if (preferences.libraryAsList().getOrDefault()) { + (swipe_refresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply { + spanCount = libraryFragment.mangaPerRow + } + } else { + (swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply { + layoutManager = LinearLayoutManager(context) + } + } - //set up list - library_list.setHasFixedSize(true) - library_list.layoutManager = LinearLayoutManager(activity) - library_list.recycledViewPool = libraryFragment.pool - (library_list.layoutManager as LinearLayoutManager).recycleChildrenOnDetach = true - library_list.adapter = adapter + (recycler.layoutManager as LinearLayoutManager).recycleChildrenOnDetach = true + recycler.recycledViewPool = libraryFragment.pool + recycler.setHasFixedSize(true) + recycler.adapter = adapter + swipe_refresh.addView(recycler) if (libraryFragment.actionMode != null) { setSelectionMode(FlexibleAdapter.MODE_MULTI) } - numColumnsSubscription = getColumnsPreferenceForCurrentOrientation().asObservable() - .doOnNext { recycler.spanCount = it } - .skip(1) - // Set again the adapter to recalculate the covers height - .subscribe { recycler.adapter = adapter } - searchSubscription = libraryPresenter.searchSubject.subscribe { text -> adapter.searchText = text adapter.updateDataSet() } - toggleViewSubscription = preferences.libraryAsList().asObservable() - .subscribe { onViewModeChange(it) } - - if (libraryPresenter.displayAsList != displayAsList) { - library_switcher.showNext() - displayAsList = libraryPresenter.displayAsList - } - - library_switcher.inAnimation = AnimationUtils.loadAnimation(activity, android.R.anim.fade_in) - library_switcher.outAnimation = AnimationUtils.loadAnimation(activity, android.R.anim.fade_out) - if (savedState != null) { position = savedState.getInt(POSITION_KEY) adapter.onRestoreInstanceState(savedState) @@ -157,9 +127,9 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli // Double the distance required to trigger sync swipe_refresh.setDistanceToTriggerSync((2 * 64 * resources.displayMetrics.density).toInt()) swipe_refresh.setOnRefreshListener { - if (!LibraryUpdateService.isRunning(activity)) { + if (!LibraryUpdateService.isRunning(context)) { libraryPresenter.categories.getOrNull(position)?.let { - LibraryUpdateService.start(activity, true, it) + LibraryUpdateService.start(context, true, it) context.toast(R.string.updating_category) } } @@ -169,9 +139,7 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli } override fun onDestroyView() { - numColumnsSubscription?.unsubscribe() searchSubscription?.unsubscribe() - toggleViewSubscription?.unsubscribe() super.onDestroyView() } @@ -250,7 +218,7 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli libraryPresenter.onOpenManga() // Create a new activity with the manga. - val intent = MangaActivity.newIntent(activity, manga) + val intent = MangaActivity.newIntent(context, manga) startActivity(intent) } @@ -282,18 +250,6 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli } } - /** - * Returns a preference for the number of manga per row based on the current orientation. - * - * @return the preference. - */ - fun getColumnsPreferenceForCurrentOrientation(): Preference { - return if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) - libraryPresenter.preferences.portraitColumns() - else - libraryPresenter.preferences.landscapeColumns() - } - /** * Sets the mode for the adapter. * @@ -306,15 +262,6 @@ class LibraryCategoryFragment : BaseFragment(), FlexibleViewHolder.OnListItemCli } } - fun onViewModeChange(isList: Boolean) { - //do nothing if the display does not need to change - if (isList == displayAsList) return - - //else change view and display mode - library_switcher.showNext() - displayAsList = isList - } - /** * Property to get the library fragment. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt index bd5784c41..0c3f997f7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.library import android.app.Activity import android.content.Intent +import android.content.res.Configuration import android.os.Bundle import android.support.design.widget.TabLayout import android.support.v4.view.ViewPager @@ -10,6 +11,7 @@ import android.support.v7.widget.RecyclerView import android.support.v7.widget.SearchView import android.view.* import com.afollestad.materialdialogs.MaterialDialog +import com.f2prateek.rx.preferences.Preference import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Category @@ -24,6 +26,7 @@ import eu.kanade.tachiyomi.util.toast import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.fragment_library.* import nucleus.factory.RequiresPresenter +import rx.Subscription import uy.kohesive.injekt.injectLazy import java.io.IOException @@ -61,11 +64,6 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback */ private var query: String? = null - /** - * Display mode of the library (list or grid mode). - */ - private var displayMode: MenuItem? = null - /** * Action mode for manga selection. */ @@ -87,10 +85,18 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback */ var isFilterUnread = false + /** + * Number of manga per row in grid mode. + */ + var mangaPerRow = 0 + private set + /** * A pool to share view holders between all the registered categories (fragments). */ - val pool = RecyclerView.RecycledViewPool() + var pool = RecyclerView.RecycledViewPool() + + private var numColumnsSubscription: Subscription? = null companion object { /** @@ -148,6 +154,12 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback } else { activeCategory = presenter.preferences.lastUsedCategory().getOrDefault() } + + numColumnsSubscription = getColumnsPreferenceForCurrentOrientation().asObservable() + .doOnNext { mangaPerRow = it } + .skip(1) + // Set again the adapter to recalculate the covers height + .subscribe { reattachAdapter() } } override fun onResume() { @@ -156,6 +168,7 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback } override fun onDestroyView() { + numColumnsSubscription?.unsubscribe() tabs.setupWithViewPager(null) tabs.visibility = View.GONE super.onDestroyView() @@ -197,17 +210,6 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback } }) - //set the icon for the display mode button - displayMode = menu.findItem(R.id.action_library_display_mode).apply { - val icon = if (preferences.libraryAsList().getOrDefault()) - R.drawable.ic_view_module_white_24dp - else - R.drawable.ic_view_list_white_24dp - - setIcon(icon) - } - - } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -257,27 +259,40 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback */ private fun onFilterCheckboxChanged() { presenter.updateLibrary() - adapter.notifyDataSetChanged() adapter.refreshRegisteredAdapters() activity.supportInvalidateOptionsMenu() } /** - * swap display mode + * Swap display mode */ private fun swapDisplayMode() { - presenter.swapDisplayMode() - val isListMode = presenter.displayAsList - val icon = if (isListMode) - R.drawable.ic_view_module_white_24dp - else - R.drawable.ic_view_list_white_24dp - - displayMode?.setIcon(icon) - + reattachAdapter() } + /** + * Reattaches the adapter to the view pager to recreate fragments + */ + private fun reattachAdapter() { + pool.clear() + pool = RecyclerView.RecycledViewPool() + val position = view_pager.currentItem + view_pager.adapter = adapter + view_pager.currentItem = position + } + + /** + * Returns a preference for the number of manga per row based on the current orientation. + * + * @return the preference. + */ + private fun getColumnsPreferenceForCurrentOrientation(): Preference { + return if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) + preferences.portraitColumns() + else + preferences.landscapeColumns() + } /** * Updates the query. @@ -289,7 +304,7 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback // Notify the subject the query has changed. if (isResumed) { - presenter.searchSubject?.onNext(query) + presenter.searchSubject.onNext(query) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt index a9f2cfb23..efdd42200 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt @@ -11,8 +11,10 @@ import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder * @param listener a listener to react to the single tap and long tap events. */ -abstract class LibraryHolder(private val view: View, adapter: LibraryCategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener) - : FlexibleViewHolder(view, adapter, listener) { +abstract class LibraryHolder(private val view: View, + adapter: LibraryCategoryAdapter, + listener: FlexibleViewHolder.OnListItemClickListener) +: FlexibleViewHolder(view, adapter, listener) { /** * Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 5f44089f8..2173be875 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -71,12 +71,6 @@ class LibraryPresenter : BasePresenter() { */ val downloadManager: DownloadManager by injectLazy() - /** - * display the library as a list? - */ - var displayAsList: Boolean = false - private set - companion object { /** * Id of the restartable that listens for library updates. @@ -95,16 +89,6 @@ class LibraryPresenter : BasePresenter() { start(GET_LIBRARY) } - add(preferences.libraryAsList().asObservable().subscribe { setDisplayMode(it) }) - } - - /** - * Sets the display mode - * - * @param asList display as list or not - */ - fun setDisplayMode(asList: Boolean) { - displayAsList = asList } /** @@ -305,6 +289,7 @@ class LibraryPresenter : BasePresenter() { * Changes the active display mode. */ fun swapDisplayMode() { + val displayAsList = preferences.libraryAsList().getOrDefault() preferences.libraryAsList().set(!displayAsList) } diff --git a/app/src/main/res/layout/fragment_library_category.xml b/app/src/main/res/layout/fragment_library_category.xml index bc31c39c8..a0614ea62 100644 --- a/app/src/main/res/layout/fragment_library_category.xml +++ b/app/src/main/res/layout/fragment_library_category.xml @@ -1,36 +1,14 @@ - + - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/library_grid_recycler.xml b/app/src/main/res/layout/library_grid_recycler.xml new file mode 100644 index 000000000..fa4563430 --- /dev/null +++ b/app/src/main/res/layout/library_grid_recycler.xml @@ -0,0 +1,10 @@ + + diff --git a/app/src/main/res/layout/library_list_recycler.xml b/app/src/main/res/layout/library_list_recycler.xml new file mode 100644 index 000000000..d3dfbc044 --- /dev/null +++ b/app/src/main/res/layout/library_list_recycler.xml @@ -0,0 +1,10 @@ + + +