Эх сурвалжийг харах

Dynamic recyclerview inflation for the library view and better swap handling

len 8 жил өмнө
parent
commit
e95fcf6172

+ 0 - 1
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
 

+ 6 - 11
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
-
 }

+ 19 - 72
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
+        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)
+            }
+        }
+
+        (recycler.layoutManager as LinearLayoutManager).recycleChildrenOnDetach = true
         recycler.recycledViewPool = libraryFragment.pool
+        recycler.setHasFixedSize(true)
         recycler.adapter = adapter
-
-        //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
+        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.
      */

+ 43 - 28
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<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)
         }
     }
 

+ 4 - 2
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

+ 1 - 16
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -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)
     }
 

+ 4 - 26
app/src/main/res/layout/fragment_library_category.xml

@@ -1,36 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             xmlns:tools="http://schemas.android.com/tools"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent">
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
 
     <android.support.v4.widget.SwipeRefreshLayout
         android:id="@+id/swipe_refresh"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-        <ViewSwitcher
-            android:id="@+id/library_switcher"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1">
-
-            <eu.kanade.tachiyomi.widget.AutofitRecyclerView
-                android:id="@+id/recycler"
-                style="@style/Theme.Widget.GridView"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:columnWidth="140dp"
-                tools:listitem="@layout/item_catalogue_grid"/>
-
-            <android.support.v7.widget.RecyclerView
-                android:id="@+id/library_list"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:paddingTop="@dimen/material_component_lists_padding_above_list"
-                tools:listitem="@layout/item_library_list"/>
-
-        </ViewSwitcher>
     </android.support.v4.widget.SwipeRefreshLayout>
 
 </FrameLayout>

+ 10 - 0
app/src/main/res/layout/library_grid_recycler.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<eu.kanade.tachiyomi.widget.AutofitRecyclerView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/library_grid"
+    style="@style/Theme.Widget.GridView"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:columnWidth="140dp"
+    tools:listitem="@layout/item_catalogue_grid" />

+ 10 - 0
app/src/main/res/layout/library_list_recycler.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v7.widget.RecyclerView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/library_list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="@dimen/material_component_lists_padding_above_list"
+    tools:listitem="@layout/item_library_list" />
+