mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-19 05:09:17 +01:00
Replace page fragments with views
This commit is contained in:
parent
9cf5a4cac0
commit
c0a0d60c87
@ -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
|
|
||||||
|
|
||||||
}
|
}
|
@ -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))
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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>
|
Loading…
Reference in New Issue
Block a user