mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Dynamic recyclerview inflation for the library view and better swap handling
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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<Int> { | ||||
|         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. | ||||
|      */ | ||||
|   | ||||
| @@ -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<LibraryPresenter>(), 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<LibraryPresenter>(), 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<LibraryPresenter>(), 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<LibraryPresenter>(), ActionMode.Callback | ||||
|     } | ||||
|  | ||||
|     override fun onDestroyView() { | ||||
|         numColumnsSubscription?.unsubscribe() | ||||
|         tabs.setupWithViewPager(null) | ||||
|         tabs.visibility = View.GONE | ||||
|         super.onDestroyView() | ||||
| @@ -197,17 +210,6 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), 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<LibraryPresenter>(), 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<Int> { | ||||
|         return if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) | ||||
|             preferences.portraitColumns() | ||||
|         else | ||||
|             preferences.landscapeColumns() | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates the query. | ||||
| @@ -289,7 +304,7 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback | ||||
|  | ||||
|         // Notify the subject the query has changed. | ||||
|         if (isResumed) { | ||||
|             presenter.searchSubject?.onNext(query) | ||||
|             presenter.searchSubject.onNext(query) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -71,12 +71,6 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() { | ||||
|      */ | ||||
|     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<LibraryFragment>() { | ||||
|             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<LibraryFragment>() { | ||||
|      * Changes the active display mode. | ||||
|      */ | ||||
|     fun swapDisplayMode() { | ||||
|         val displayAsList = preferences.libraryAsList().getOrDefault() | ||||
|         preferences.libraryAsList().set(!displayAsList) | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user