Reversed reader mode #15
This commit is contained in:
@@ -4,7 +4,8 @@ enum class ReaderMode(val id: Int) {
|
||||
|
||||
UNKNOWN(0),
|
||||
STANDARD(1),
|
||||
WEBTOON(2);
|
||||
WEBTOON(2),
|
||||
REVERSED(3);
|
||||
|
||||
companion object {
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
import org.koitharu.kotatsu.ui.base.BaseFullscreenActivity
|
||||
import org.koitharu.kotatsu.ui.reader.base.AbstractReader
|
||||
import org.koitharu.kotatsu.ui.reader.reversed.ReversedReaderFragment
|
||||
import org.koitharu.kotatsu.ui.reader.standard.PagerReaderFragment
|
||||
import org.koitharu.kotatsu.ui.reader.thumbnails.OnPageSelectListener
|
||||
import org.koitharu.kotatsu.ui.reader.thumbnails.PagesThumbnailsSheet
|
||||
@@ -121,6 +122,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
replace(R.id.container, WebtoonReaderFragment.newInstance(state))
|
||||
}
|
||||
}
|
||||
ReaderMode.REVERSED -> if (currentReader !is ReversedReaderFragment) {
|
||||
supportFragmentManager.commit {
|
||||
replace(R.id.container, ReversedReaderFragment.newInstance(state))
|
||||
}
|
||||
}
|
||||
else -> if (currentReader !is PagerReaderFragment) {
|
||||
supportFragmentManager.commit {
|
||||
replace(R.id.container, PagerReaderFragment.newInstance(state))
|
||||
@@ -130,6 +136,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
toolbar_bottom.menu.findItem(R.id.action_reader_mode).setIcon(
|
||||
when (mode) {
|
||||
ReaderMode.WEBTOON -> R.drawable.ic_script
|
||||
ReaderMode.REVERSED -> R.drawable.ic_read_reversed
|
||||
else -> R.drawable.ic_book_page
|
||||
}
|
||||
)
|
||||
@@ -159,6 +166,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
supportFragmentManager, when (reader) {
|
||||
is PagerReaderFragment -> ReaderMode.STANDARD
|
||||
is WebtoonReaderFragment -> ReaderMode.WEBTOON
|
||||
is ReversedReaderFragment -> ReaderMode.REVERSED
|
||||
else -> ReaderMode.UNKNOWN
|
||||
}
|
||||
)
|
||||
|
||||
@@ -32,10 +32,12 @@ class ReaderConfigDialog : AlertDialogFragment(R.layout.dialog_reader_config),
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
button_standard.isChecked = mode == ReaderMode.STANDARD
|
||||
button_reversed.isChecked = mode == ReaderMode.REVERSED
|
||||
button_webtoon.isChecked = mode == ReaderMode.WEBTOON
|
||||
|
||||
button_ok.setOnClickListener(this)
|
||||
button_standard.setOnClickListener(this)
|
||||
button_reversed.setOnClickListener(this)
|
||||
button_webtoon.setOnClickListener(this)
|
||||
}
|
||||
|
||||
@@ -48,6 +50,7 @@ class ReaderConfigDialog : AlertDialogFragment(R.layout.dialog_reader_config),
|
||||
}
|
||||
R.id.button_standard -> mode = ReaderMode.STANDARD
|
||||
R.id.button_webtoon -> mode = ReaderMode.WEBTOON
|
||||
R.id.button_reversed -> mode = ReaderMode.REVERSED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koitharu.kotatsu.core.model.MangaPage
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
|
||||
abstract class BaseReaderAdapter(private val pages: GroupedList<Long, MangaPage>) :
|
||||
abstract class BaseReaderAdapter(protected val pages: GroupedList<Long, MangaPage>) :
|
||||
RecyclerView.Adapter<BaseViewHolder<MangaPage, Unit>>() {
|
||||
|
||||
init {
|
||||
@@ -18,25 +18,25 @@ abstract class BaseReaderAdapter(private val pages: GroupedList<Long, MangaPage>
|
||||
holder.bind(item, Unit)
|
||||
}
|
||||
|
||||
fun getItem(position: Int) = pages[position]
|
||||
open fun getItem(position: Int) = pages[position]
|
||||
|
||||
fun notifyItemsAppended(count: Int) {
|
||||
open fun notifyItemsAppended(count: Int) {
|
||||
notifyItemRangeInserted(pages.size - count, count)
|
||||
}
|
||||
|
||||
fun notifyItemsPrepended(count: Int) {
|
||||
open fun notifyItemsPrepended(count: Int) {
|
||||
notifyItemRangeInserted(0, count)
|
||||
}
|
||||
|
||||
fun notifyItemsRemovedStart(count: Int) {
|
||||
open fun notifyItemsRemovedStart(count: Int) {
|
||||
notifyItemRangeRemoved(0, count)
|
||||
}
|
||||
|
||||
fun notifyItemsRemovedEnd(count: Int) {
|
||||
open fun notifyItemsRemovedEnd(count: Int) {
|
||||
notifyItemRangeRemoved(pages.size - count, count)
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int) = pages[position].id
|
||||
open override fun getItemId(position: Int) = pages[position].id
|
||||
|
||||
final override fun getItemCount() = pages.size
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.koitharu.kotatsu.ui.reader.reversed
|
||||
|
||||
import android.view.View
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
|
||||
class ReversedPageAnimTransformer : ViewPager2.PageTransformer {
|
||||
|
||||
override fun transformPage(page: View, position: Float) {
|
||||
with(page) {
|
||||
val pageWidth = width
|
||||
when {
|
||||
position > 1 -> alpha = 0f
|
||||
position >= 0 -> {
|
||||
alpha = 1f
|
||||
translationX = 0f
|
||||
translationZ = 0f
|
||||
scaleX = 1 + FACTOR * position
|
||||
scaleY = 1f
|
||||
}
|
||||
position >= -1 -> {
|
||||
alpha = 1f
|
||||
translationX = pageWidth * -position
|
||||
translationZ = -1f
|
||||
scaleX = 1f
|
||||
scaleY = 1f
|
||||
}
|
||||
else -> alpha = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
const val FACTOR = 0.1f
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.koitharu.kotatsu.ui.reader.reversed
|
||||
|
||||
import android.view.ViewGroup
|
||||
import org.koitharu.kotatsu.core.model.MangaPage
|
||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||
import org.koitharu.kotatsu.ui.reader.PageLoader
|
||||
import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter
|
||||
import org.koitharu.kotatsu.ui.reader.base.GroupedList
|
||||
import org.koitharu.kotatsu.ui.reader.standard.PageHolder
|
||||
|
||||
class ReversedPagesAdapter(
|
||||
pages: GroupedList<Long, MangaPage>,
|
||||
private val loader: PageLoader
|
||||
) : BaseReaderAdapter(pages) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup) = PageHolder(parent, loader)
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder<MangaPage, Unit>, position: Int) {
|
||||
super.onBindViewHolder(holder, reversed(position))
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): MangaPage {
|
||||
return super.getItem(reversed(position))
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return super.getItemId(reversed(position))
|
||||
}
|
||||
|
||||
override fun notifyItemsAppended(count: Int) {
|
||||
super.notifyItemsPrepended(count)
|
||||
}
|
||||
|
||||
override fun notifyItemsPrepended(count: Int) {
|
||||
super.notifyItemsAppended(count)
|
||||
}
|
||||
|
||||
override fun notifyItemsRemovedStart(count: Int) {
|
||||
super.notifyItemsRemovedEnd(count)
|
||||
}
|
||||
|
||||
override fun notifyItemsRemovedEnd(count: Int) {
|
||||
super.notifyItemsRemovedStart(count)
|
||||
}
|
||||
|
||||
private fun reversed(position: Int) = pages.size - position - 1
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.koitharu.kotatsu.ui.reader.reversed
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.main.fragment_reader_standard.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaPage
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.ui.reader.ReaderState
|
||||
import org.koitharu.kotatsu.ui.reader.base.AbstractReader
|
||||
import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter
|
||||
import org.koitharu.kotatsu.ui.reader.base.GroupedList
|
||||
import org.koitharu.kotatsu.ui.reader.standard.PageAnimTransformer
|
||||
import org.koitharu.kotatsu.ui.reader.standard.PagerPaginationListener
|
||||
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
||||
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||
|
||||
class ReversedReaderFragment : AbstractReader(R.layout.fragment_reader_standard),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private var paginationListener: PagerPaginationListener? = null
|
||||
private val settings by inject<AppSettings>()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
paginationListener = PagerPaginationListener(adapter!!, 2, this)
|
||||
pager.adapter = adapter
|
||||
if (settings.readerAnimation) {
|
||||
pager.setPageTransformer(ReversedPageAnimTransformer())
|
||||
}
|
||||
pager.offscreenPageLimit = 2
|
||||
pager.registerOnPageChangeCallback(paginationListener!!)
|
||||
pager.doOnPageChanged {
|
||||
notifyPageChanged(reversed(it))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
settings.subscribe(this)
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
settings.unsubscribe(this)
|
||||
super.onDetach()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
paginationListener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onCreateAdapter(dataSet: GroupedList<Long, MangaPage>): BaseReaderAdapter {
|
||||
return ReversedPagesAdapter(dataSet, loader)
|
||||
}
|
||||
|
||||
override val itemsCount: Int
|
||||
get() = adapter?.itemCount ?: 0
|
||||
|
||||
override fun getCurrentItem() = reversed(pager.currentItem)
|
||||
|
||||
override fun setCurrentItem(position: Int, isSmooth: Boolean) {
|
||||
pager.setCurrentItem(reversed(position), isSmooth)
|
||||
}
|
||||
|
||||
override fun getCurrentPageScroll() = 0
|
||||
|
||||
override fun restorePageScroll(position: Int, scroll: Int) = Unit
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
when (key) {
|
||||
getString(R.string.key_reader_animation) -> {
|
||||
if (settings.readerAnimation) {
|
||||
pager.setPageTransformer(PageAnimTransformer())
|
||||
} else {
|
||||
pager.setPageTransformer(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reversed(position: Int) = (itemsCount - position - 1).coerceAtLeast(0)
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(state: ReaderState) = ReversedReaderFragment().withArgs(1) {
|
||||
putParcelable(ARG_STATE, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user