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
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) }
fun initialize(reader: PagerReader, page: Page?) {
val activity = reader.activity as ReaderActivity
/**
* Text color for white theme.
*/
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 (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
}

View File

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

View File

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

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"?>
<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>