Replace page fragments with views

This commit is contained in:
len 2016-07-30 15:51:49 +02:00
parent 9cf5a4cac0
commit c0a0d60c87
5 changed files with 116 additions and 162 deletions

View File

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

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.reader.viewer.pager package eu.kanade.tachiyomi.ui.reader.viewer.pager
import android.support.v4.content.ContextCompat
import android.view.GestureDetector import android.view.GestureDetector
import android.view.MotionEvent import android.view.MotionEvent
import android.view.ViewGroup import android.view.ViewGroup
@ -90,13 +91,23 @@ abstract class PagerReader : BaseReader() {
var zoomType = 1 var zoomType = 1
private set 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. * Initializes the pager.
* *
* @param pager the pager to initialize. * @param pager the pager to initialize.
*/ */
protected fun initializePager(pager: Pager) { protected fun initializePager(pager: Pager) {
adapter = PagerReaderAdapter(childFragmentManager) adapter = PagerReaderAdapter(this)
this.pager = pager.apply { this.pager = pager.apply {
setLayoutParams(ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)) setLayoutParams(ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT))

View File

@ -1,19 +1,16 @@
package eu.kanade.tachiyomi.ui.reader.viewer.pager package eu.kanade.tachiyomi.ui.reader.viewer.pager
import android.support.v4.app.Fragment import android.view.View
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter
import android.support.v4.view.PagerAdapter
import android.view.ViewGroup import android.view.ViewGroup
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Page 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. * 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. * Pages stored in the adapter.
@ -24,6 +21,12 @@ class PagerReaderAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
notifyDataSetChanged() 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. * Returns the number of pages.
* *
@ -33,46 +36,4 @@ class PagerReaderAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
return pages?.size ?: 0 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)
}
} }

View File

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

View File

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