Переглянути джерело

Replace page fragments with views

len 8 роки тому
батько
коміт
c0a0d60c87

+ 61 - 109
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.kt → app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PageView.kt

@@ -1,23 +1,23 @@
 package eu.kanade.tachiyomi.ui.reader.viewer.pager
 
-import android.graphics.PointF
-import android.os.Bundle
-import android.support.v4.content.ContextCompat
-import android.view.LayoutInflater
+import android.content.Context
+import android.util.AttributeSet
 import android.view.MotionEvent
 import android.view.View
-import android.view.ViewGroup
+import android.widget.FrameLayout
 import com.davemorrissey.labs.subscaleview.ImageSource
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.source.model.Page
-import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment
 import eu.kanade.tachiyomi.ui.reader.ReaderActivity
 import eu.kanade.tachiyomi.ui.reader.viewer.base.PageDecodeErrorLayout
+import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerReader.Companion.ALIGN_CENTER
+import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerReader.Companion.ALIGN_LEFT
+import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerReader.Companion.ALIGN_RIGHT
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.horizontal.RightToLeftReader
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.vertical.VerticalReader
-import kotlinx.android.synthetic.main.chapter_image.*
-import kotlinx.android.synthetic.main.item_pager_reader.*
+import kotlinx.android.synthetic.main.chapter_image.view.*
+import kotlinx.android.synthetic.main.item_pager_reader.view.*
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers
@@ -25,41 +25,15 @@ import rx.subjects.PublishSubject
 import rx.subjects.SerializedSubject
 import java.io.File
 import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicInteger
 
-/**
- * Fragment for a single page of the ViewPager reader.
- * All the elements from the layout file "item_pager_reader" are available in this class.
- */
-class PagerReaderFragment : BaseFragment() {
-
-    companion object {
-        /**
-         * Creates a new instance of this fragment.
-         *
-         * @return a new instance of [PagerReaderFragment].
-         */
-        fun newInstance(): PagerReaderFragment {
-            return PagerReaderFragment()
-        }
-    }
+class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
+: FrameLayout(context, attrs) {
 
     /**
      * Page of a chapter.
      */
     var page: Page? = null
-        set(value) {
-            field = value
-            // Observe status if the view is initialized
-            if (view != null) {
-                observeStatus()
-            }
-        }
-
-    /**
-     * Position of the fragment in the adapter.
-     */
-    var position = -1
+        private set
 
     /**
      * Subscription for progress changes of the page.
@@ -71,47 +45,34 @@ class PagerReaderFragment : BaseFragment() {
      */
     private var statusSubscription: Subscription? = null
 
-    /**
-     * Text color for black theme.
-     */
-    private val whiteColor by lazy { ContextCompat.getColor(context, R.color.textColorSecondaryDark) }
-
-    /**
-     * Text color for white theme.
-     */
-    private val blackColor by lazy { ContextCompat.getColor(context, R.color.textColorSecondaryLight) }
+    fun initialize(reader: PagerReader, page: Page?) {
+        val activity = reader.activity as ReaderActivity
 
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?): View? {
-        return inflater.inflate(R.layout.item_pager_reader, container, false)
-    }
-
-    override fun onViewCreated(view: View, savedState: Bundle?) {
-        if (readerActivity.readerTheme == ReaderActivity.BLACK_THEME) {
-            progress_text.setTextColor(whiteColor)
-        } else {
-            progress_text.setTextColor(blackColor)
+        when (activity.readerTheme) {
+            ReaderActivity.BLACK_THEME -> progress_text.setTextColor(reader.whiteColor)
+            ReaderActivity.WHITE_THEME -> progress_text.setTextColor(reader.blackColor)
         }
 
-        if (pagerReader is RightToLeftReader) {
-            view.rotation = -180f
+        if (reader is RightToLeftReader) {
+            rotation = -180f
         }
 
         with(image_view) {
-            setMaxBitmapDimensions(readerActivity.maxBitmapSize)
-            setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED)
-            setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE)
-            setMinimumScaleType(pagerReader.scaleType)
+            setMaxBitmapDimensions((reader.activity as ReaderActivity).maxBitmapSize)
+            setDoubleTapZoomStyle(com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.ZOOM_FOCUS_FIXED)
+            setPanLimit(com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.PAN_LIMIT_INSIDE)
+            setMinimumScaleType(reader.scaleType)
             setMinimumDpi(50)
-            setRegionDecoderClass(pagerReader.regionDecoderClass)
-            setBitmapDecoderClass(pagerReader.bitmapDecoderClass)
-            setVerticalScrollingParent(pagerReader is VerticalReader)
-            setOnTouchListener { v, motionEvent -> pagerReader.gestureDetector.onTouchEvent(motionEvent) }
+            setRegionDecoderClass(reader.regionDecoderClass)
+            setBitmapDecoderClass(reader.bitmapDecoderClass)
+            setVerticalScrollingParent(reader is VerticalReader)
+            setOnTouchListener { v, motionEvent -> reader.gestureDetector.onTouchEvent(motionEvent) }
             setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
                 override fun onReady() {
-                    when (pagerReader.zoomType) {
-                        PagerReader.ALIGN_LEFT -> setScaleAndCenter(scale, PointF(0f, 0f))
-                        PagerReader.ALIGN_RIGHT -> setScaleAndCenter(scale, PointF(sWidth.toFloat(), 0f))
-                        PagerReader.ALIGN_CENTER -> {
+                    when (reader.zoomType) {
+                        ALIGN_LEFT -> setScaleAndCenter(scale, android.graphics.PointF(0f, 0f))
+                        ALIGN_RIGHT -> setScaleAndCenter(scale, android.graphics.PointF(sWidth.toFloat(), 0f))
+                        ALIGN_CENTER -> {
                             val newCenter = center
                             newCenter.y = 0f
                             setScaleAndCenter(scale, newCenter)
@@ -120,27 +81,34 @@ class PagerReaderFragment : BaseFragment() {
                 }
 
                 override fun onImageLoadError(e: Exception) {
-                    onImageDecodeError()
+                    onImageDecodeError(activity)
                 }
             })
         }
 
         retry_button.setOnTouchListener { v, event ->
             if (event.action == MotionEvent.ACTION_UP) {
-                readerActivity.presenter.retryPage(page)
+                activity.presenter.retryPage(page)
             }
             true
         }
 
-        observeStatus()
+        if (page != null) {
+            this.page = page
+            observeStatus()
+        }
     }
 
-    override fun onDestroyView() {
+    fun cleanup() {
         unsubscribeProgress()
         unsubscribeStatus()
         image_view.setOnTouchListener(null)
         image_view.setOnImageEventListener(null)
-        super.onDestroyView()
+    }
+
+    override fun onDetachedFromWindow() {
+        cleanup()
+        super.onDetachedFromWindow()
     }
 
     /**
@@ -149,33 +117,31 @@ class PagerReaderFragment : BaseFragment() {
      * @see processStatus
      */
     private fun observeStatus() {
-        page?.let { page ->
-            val statusSubject = SerializedSubject(PublishSubject.create<Int>())
-            page.setStatusSubject(statusSubject)
+        statusSubscription?.unsubscribe()
+        val page = page ?: return
 
-            statusSubscription?.unsubscribe()
-            statusSubscription = statusSubject.startWith(page.status)
-                    .observeOn(AndroidSchedulers.mainThread())
-                    .subscribe { processStatus(it) }
-        }
+        val statusSubject = SerializedSubject(PublishSubject.create<Int>())
+        page.setStatusSubject(statusSubject)
+
+        statusSubscription = statusSubject.startWith(page.status)
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe { processStatus(it) }
     }
 
     /**
      * Observes the progress of the page and updates view.
      */
     private fun observeProgress() {
-        val currentValue = AtomicInteger(-1)
-
         progressSubscription?.unsubscribe()
+        val page = page ?: return
+
         progressSubscription = Observable.interval(100, TimeUnit.MILLISECONDS)
+                .map { page.progress }
+                .distinctUntilChanged()
                 .onBackpressureLatest()
                 .observeOn(AndroidSchedulers.mainThread())
-                .subscribe {
-                    // Refresh UI only if progress change
-                    if (page?.progress != currentValue.get()) {
-                        currentValue.set(page?.progress ?: 0)
-                        progress_text.text = getString(R.string.download_progress, currentValue.get())
-                    }
+                .subscribe { progress ->
+                    progress_text.text = context.getString(R.string.download_progress, progress)
                 }
     }
 
@@ -269,27 +235,13 @@ class PagerReaderFragment : BaseFragment() {
     /**
      * Called when an image fails to decode.
      */
-    private fun onImageDecodeError() {
-        val view = view as? ViewGroup ?: return
-
+    private fun onImageDecodeError(activity: ReaderActivity) {
         page?.let { page ->
-            val errorLayout = PageDecodeErrorLayout(context, page, readerActivity.readerTheme,
-                    { readerActivity.presenter.retryPage(page) })
+            val errorLayout = PageDecodeErrorLayout(context, page, activity.readerTheme,
+                    { activity.presenter.retryPage(page) })
 
-            view.addView(errorLayout)
+            addView(errorLayout)
         }
     }
 
-    /**
-     * Property to get the reader activity.
-     */
-    private val readerActivity: ReaderActivity
-        get() = activity as ReaderActivity
-
-    /**
-     * Property to get the pager reader.
-     */
-    private val pagerReader: PagerReader
-        get() = parentFragment as PagerReader
-
-}
+}

+ 12 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.kt

@@ -1,5 +1,6 @@
 package eu.kanade.tachiyomi.ui.reader.viewer.pager
 
+import android.support.v4.content.ContextCompat
 import android.view.GestureDetector
 import android.view.MotionEvent
 import android.view.ViewGroup
@@ -90,13 +91,23 @@ abstract class PagerReader : BaseReader() {
     var zoomType = 1
         private set
 
+    /**
+     * Text color for black theme.
+     */
+    val whiteColor by lazy { ContextCompat.getColor(context, R.color.textColorSecondaryDark) }
+
+    /**
+     * Text color for white theme.
+     */
+    val blackColor by lazy { ContextCompat.getColor(context, R.color.textColorSecondaryLight) }
+
     /**
      * Initializes the pager.
      *
      * @param pager the pager to initialize.
      */
     protected fun initializePager(pager: Pager) {
-        adapter = PagerReaderAdapter(childFragmentManager)
+        adapter = PagerReaderAdapter(this)
 
         this.pager = pager.apply {
             setLayoutParams(ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT))

+ 11 - 50
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderAdapter.kt

@@ -1,19 +1,16 @@
 package eu.kanade.tachiyomi.ui.reader.viewer.pager
 
-import android.support.v4.app.Fragment
-import android.support.v4.app.FragmentManager
-import android.support.v4.app.FragmentStatePagerAdapter
-import android.support.v4.view.PagerAdapter
+import android.view.View
 import android.view.ViewGroup
-
+import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.source.model.Page
+import eu.kanade.tachiyomi.util.inflate
+import eu.kanade.tachiyomi.widget.ViewPagerAdapter
 
 /**
  * Adapter of pages for a ViewPager.
- *
- * @param fm the fragment manager.
  */
-class PagerReaderAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
+class PagerReaderAdapter(private val reader: PagerReader) : ViewPagerAdapter() {
 
     /**
      * Pages stored in the adapter.
@@ -24,6 +21,12 @@ class PagerReaderAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
             notifyDataSetChanged()
         }
 
+    override fun createView(container: ViewGroup, position: Int): View {
+        val view = container.inflate(R.layout.item_pager_reader) as PageView
+        view.initialize(reader, pages?.getOrNull(position))
+        return view
+    }
+
     /**
      * Returns the number of pages.
      *
@@ -33,46 +36,4 @@ class PagerReaderAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
         return pages?.size ?: 0
     }
 
-    /**
-     * Creates a new fragment for the given position when it's called.
-     *
-     * @param position the position to instantiate.
-     * @return a fragment for the given position.
-     */
-    override fun getItem(position: Int): Fragment {
-        return PagerReaderFragment.newInstance()
-    }
-
-    /**
-     * Instantiates a fragment in the given position.
-     *
-     * @param container the parent view.
-     * @param position the position to instantiate.
-     * @return an instance of a fragment for the given position.
-     */
-    override fun instantiateItem(container: ViewGroup, position: Int): Any {
-        val f = super.instantiateItem(container, position) as PagerReaderFragment
-        f.page = pages!![position]
-        f.position = position
-        return f
-    }
-
-    /**
-     * Returns the position of a given item.
-     *
-     * @param obj the item to find its position.
-     * @return the position for the item.
-     */
-    override fun getItemPosition(obj: Any): Int {
-        val f = obj as PagerReaderFragment
-        val position = f.position
-        if (position >= 0 && position < count) {
-            if (pages!![position] === f.page) {
-                return PagerAdapter.POSITION_UNCHANGED
-            } else {
-                return PagerAdapter.POSITION_NONE
-            }
-        }
-        return super.getItemPosition(obj)
-    }
 }

+ 30 - 0
app/src/main/java/eu/kanade/tachiyomi/widget/ViewPagerAdapter.kt

@@ -0,0 +1,30 @@
+package eu.kanade.tachiyomi.widget
+
+import android.support.v4.view.PagerAdapter
+import android.view.View
+import android.view.ViewGroup
+
+abstract class ViewPagerAdapter : PagerAdapter() {
+
+    protected abstract fun createView(container: ViewGroup, position: Int): View
+
+    protected open fun destroyView(container: ViewGroup, position: Int, view: View) {
+    }
+
+    override fun instantiateItem(container: ViewGroup, position: Int): Any {
+        val view = createView(container, position)
+        container.addView(view)
+        return view
+    }
+
+    override fun destroyItem(container: ViewGroup, position: Int, obj: Any) {
+        val view = obj as View
+        destroyView(container, position, view)
+        container.removeView(view)
+    }
+
+    override fun isViewFromObject(view: View, obj: Any): Boolean {
+        return view === obj
+    }
+
+}

+ 2 - 2
app/src/main/res/layout/item_pager_reader.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<FrameLayout
+<eu.kanade.tachiyomi.ui.reader.viewer.pager.PageView
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     xmlns:android="http://schemas.android.com/apk/res/android">
@@ -40,4 +40,4 @@
         android:layout_gravity="center"
         android:visibility="gone"/>
 
-</FrameLayout>
+</eu.kanade.tachiyomi.ui.reader.viewer.pager.PageView>