Refactor common chapter transition views into separate view

This commit is contained in:
arkon 2020-09-04 16:25:08 -04:00
parent 66baf01e43
commit 86e59977de
4 changed files with 161 additions and 259 deletions

View file

@ -0,0 +1,101 @@
package eu.kanade.tachiyomi.ui.reader.viewer
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.widget.LinearLayout
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import kotlin.math.floor
import kotlinx.android.synthetic.main.reader_transition_view.view.lower_text
import kotlinx.android.synthetic.main.reader_transition_view.view.upper_text
import kotlinx.android.synthetic.main.reader_transition_view.view.warning
import kotlinx.android.synthetic.main.reader_transition_view.view.warning_text
class TransitionView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LinearLayout(context, attrs) {
init {
inflate(context, R.layout.reader_transition_view, this)
}
fun bind(transition: ChapterTransition) {
when (transition) {
is ChapterTransition.Prev -> bindPrevChapterTransition(transition)
is ChapterTransition.Next -> bindNextChapterTransition(transition)
}
missingChapterWarning(transition)
}
/**
* Binds a previous chapter transition on this view and subscribes to the page load status.
*/
private fun bindPrevChapterTransition(transition: ChapterTransition) {
val prevChapter = transition.to
val hasPrevChapter = prevChapter != null
lower_text.isVisible = hasPrevChapter
if (hasPrevChapter) {
gravity = Gravity.CENTER_VERTICAL
upper_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_current)) }
append("\n${transition.from.chapter.name}")
}
lower_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_previous)) }
append("\n${prevChapter!!.chapter.name}")
}
} else {
gravity = Gravity.CENTER
upper_text.text = context.getString(R.string.transition_no_previous)
}
}
/**
* Binds a next chapter transition on this view and subscribes to the load status.
*/
private fun bindNextChapterTransition(transition: ChapterTransition) {
val nextChapter = transition.to
val hasNextChapter = nextChapter != null
lower_text.isVisible = hasNextChapter
if (hasNextChapter) {
gravity = Gravity.CENTER_VERTICAL
upper_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_finished)) }
append("\n${transition.from.chapter.name}")
}
lower_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_next)) }
append("\n${nextChapter!!.chapter.name}")
}
} else {
gravity = Gravity.CENTER
upper_text.text = context.getString(R.string.transition_no_next)
}
}
private fun missingChapterWarning(transition: ChapterTransition) {
if (transition.to == null) {
warning.isVisible = false
return
}
val fromChapterNumber: Float = floor(transition.from.chapter.chapter_number)
val toChapterNumber: Float = floor(transition.to!!.chapter.chapter_number)
val chapterDifference = when (transition) {
is ChapterTransition.Prev -> fromChapterNumber - toChapterNumber - 1f
is ChapterTransition.Next -> toChapterNumber - fromChapterNumber - 1f
}
val hasMissingChapters = chapterDifference > 0f
warning_text.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterDifference.toInt(), chapterDifference.toInt())
warning.isVisible = hasMissingChapters
}
}

View file

@ -6,22 +6,15 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.viewer.TransitionView
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.setVectorCompat
import eu.kanade.tachiyomi.widget.ViewPagerAdapter import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import kotlin.math.floor
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -45,36 +38,6 @@ class PagerTransitionHolder(
*/ */
private var statusSubscription: Subscription? = null private var statusSubscription: Subscription? = null
private var warningContainer: LinearLayout = LinearLayout(context).apply {
val layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
layoutParams.bottomMargin = 16.dpToPx
setLayoutParams(layoutParams)
orientation = HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
}
private var warningImageView: ImageView = ImageView(context).apply {
val tintColor = context.getResourceColor(R.attr.colorOnBackground)
setVectorCompat(R.drawable.ic_warning_white_24dp, tintColor)
wrapContent()
}
private var warningTextView: TextView = TextView(context).apply {
wrapContent()
}
private var upperTextView: TextView = TextView(context).apply {
val layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
layoutParams.bottomMargin = 16.dpToPx
setLayoutParams(layoutParams)
textSize = 17.5F
}
private var lowerTextView: TextView = TextView(context).apply {
textSize = 17.5F
wrapContent()
}
/** /**
* View container of the current status of the transition page. Child views will be added * View container of the current status of the transition page. Child views will be added
* dynamically. * dynamically.
@ -90,44 +53,14 @@ class PagerTransitionHolder(
gravity = Gravity.CENTER gravity = Gravity.CENTER
val sidePadding = 64.dpToPx val sidePadding = 64.dpToPx
setPadding(sidePadding, 0, sidePadding, 0) setPadding(sidePadding, 0, sidePadding, 0)
addView(upperTextView)
warningContainer.addView(warningImageView) val transitionView = TransitionView(context)
warningContainer.addView(warningTextView) addView(transitionView)
addView(warningContainer)
addView(lowerTextView)
addView(pagesContainer) addView(pagesContainer)
when (transition) { transitionView.bind(transition)
is ChapterTransition.Prev -> bindPrevChapterTransition()
is ChapterTransition.Next -> bindNextChapterTransition()
}
missingChapterWarning() transition.to?.let { observeStatus(it) }
}
private fun missingChapterWarning() {
if (transition.to == null) {
showMissingChapterWarning(false)
return
}
val fromChapterNumber: Float = floor(transition.from.chapter.chapter_number)
val toChapterNumber: Float = floor(transition.to!!.chapter.chapter_number)
val chapterDifference = when (transition) {
is ChapterTransition.Prev -> fromChapterNumber - toChapterNumber - 1f
is ChapterTransition.Next -> toChapterNumber - fromChapterNumber - 1f
}
val hasMissingChapters = chapterDifference > 0f
warningTextView.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterDifference.toInt(), chapterDifference.toInt())
showMissingChapterWarning(hasMissingChapters)
}
private fun showMissingChapterWarning(visible: Boolean) {
warningImageView.isVisible = visible
warningTextView.isVisible = visible
} }
/** /**
@ -139,62 +72,6 @@ class PagerTransitionHolder(
statusSubscription = null statusSubscription = null
} }
/**
* Binds a next chapter transition on this view and subscribes to the load status.
*/
private fun bindNextChapterTransition() {
val nextChapter = transition.to
val hasNextChapter = nextChapter != null
lowerTextView.isVisible = hasNextChapter
if (hasNextChapter) {
gravity = Gravity.CENTER_VERTICAL
upperTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_finished)) }
append("\n${transition.from.chapter.name}")
}
lowerTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_next)) }
append("\n${nextChapter!!.chapter.name}")
}
} else {
gravity = Gravity.CENTER
upperTextView.text = context.getString(R.string.transition_no_next)
}
if (nextChapter != null) {
observeStatus(nextChapter)
}
}
/**
* Binds a previous chapter transition on this view and subscribes to the page load status.
*/
private fun bindPrevChapterTransition() {
val prevChapter = transition.to
val hasPrevChapter = prevChapter != null
lowerTextView.isVisible = hasPrevChapter
if (hasPrevChapter) {
gravity = Gravity.CENTER_VERTICAL
upperTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_current)) }
append("\n${transition.from.chapter.name}")
}
lowerTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_previous)) }
append("\n${prevChapter!!.chapter.name}")
}
} else {
gravity = Gravity.CENTER
upperTextView.text = context.getString(R.string.transition_no_previous)
}
if (prevChapter != null) {
observeStatus(prevChapter)
}
}
/** /**
* Observes the status of the page list of the next/previous chapter. Whenever there's a new * Observes the status of the page list of the next/previous chapter. Whenever there's a new
* state, the pages container is cleaned up before setting the new state. * state, the pages container is cleaned up before setting the new state.

View file

@ -3,23 +3,17 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
import android.view.Gravity import android.view.Gravity
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.isNotEmpty import androidx.core.view.isNotEmpty
import androidx.core.view.isVisible import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.viewer.TransitionView
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.setVectorCompat
import kotlin.math.floor
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -36,38 +30,7 @@ class WebtoonTransitionHolder(
*/ */
private var statusSubscription: Subscription? = null private var statusSubscription: Subscription? = null
private var warningContainer: LinearLayout = LinearLayout(context).apply { private val transitionView = TransitionView(context)
val layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
layoutParams.bottomMargin = 16.dpToPx
setLayoutParams(layoutParams)
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
}
private var warningImageView: ImageView = ImageView(context).apply {
val tintColor = context.getResourceColor(R.attr.colorOnBackground)
setVectorCompat(R.drawable.ic_warning_white_24dp, tintColor)
wrapContent()
}
private var warningTextView: TextView = TextView(context).apply {
wrapContent()
}
private var upperTextView: TextView = TextView(context).apply {
val layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
layoutParams.topMargin = 16.dpToPx
layoutParams.bottomMargin = 16.dpToPx
setLayoutParams(layoutParams)
textSize = 17.5F
}
private var lowerTextView: TextView = TextView(context).apply {
val layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
layoutParams.bottomMargin = 16.dpToPx
setLayoutParams(layoutParams)
textSize = 17.5F
}
/** /**
* View container of the current status of the transition page. Child views will be added * View container of the current status of the transition page. Child views will be added
@ -92,11 +55,7 @@ class WebtoonTransitionHolder(
setMargins(0, childMargins, 0, childMargins) setMargins(0, childMargins, 0, childMargins)
} }
layout.addView(upperTextView) layout.addView(transitionView)
warningContainer.addView(warningImageView)
warningContainer.addView(warningTextView)
layout.addView(warningContainer)
layout.addView(lowerTextView)
layout.addView(pagesContainer, childParams) layout.addView(pagesContainer, childParams)
} }
@ -104,37 +63,9 @@ class WebtoonTransitionHolder(
* Binds the given [transition] with this view holder, subscribing to its state. * Binds the given [transition] with this view holder, subscribing to its state.
*/ */
fun bind(transition: ChapterTransition) { fun bind(transition: ChapterTransition) {
when (transition) { transitionView.bind(transition)
is ChapterTransition.Prev -> bindPrevChapterTransition(transition)
is ChapterTransition.Next -> bindNextChapterTransition(transition)
}
missingChapterWarning(transition) transition.to?.let { observeStatus(it, transition) }
}
private fun missingChapterWarning(transition: ChapterTransition) {
if (transition.to == null) {
showMissingChapterWarning(false)
return
}
val fromChapterNumber: Float = floor(transition.from.chapter.chapter_number)
val toChapterNumber: Float = floor(transition.to!!.chapter.chapter_number)
val chapterDifference = when (transition) {
is ChapterTransition.Prev -> fromChapterNumber - toChapterNumber - 1f
is ChapterTransition.Next -> toChapterNumber - fromChapterNumber - 1f
}
val hasMissingChapters = chapterDifference > 0f
warningTextView.text = itemView.resources.getQuantityString(R.plurals.missing_chapters_warning, chapterDifference.toInt(), chapterDifference.toInt())
showMissingChapterWarning(hasMissingChapters)
}
private fun showMissingChapterWarning(visible: Boolean) {
warningImageView.isVisible = visible
warningTextView.isVisible = visible
} }
/** /**
@ -144,62 +75,6 @@ class WebtoonTransitionHolder(
unsubscribeStatus() unsubscribeStatus()
} }
/**
* Binds a next chapter transition on this view and subscribes to the load status.
*/
private fun bindNextChapterTransition(transition: ChapterTransition.Next) {
val nextChapter = transition.to
val hasNextChapter = nextChapter != null
lowerTextView.isVisible = hasNextChapter
if (hasNextChapter) {
layout.gravity = Gravity.CENTER_VERTICAL
upperTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_finished)) }
append("\n${transition.from.chapter.name}")
}
lowerTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_next)) }
append("\n${nextChapter!!.chapter.name}")
}
} else {
layout.gravity = Gravity.CENTER
upperTextView.text = context.getString(R.string.transition_no_next)
}
if (nextChapter != null) {
observeStatus(nextChapter, transition)
}
}
/**
* Binds a previous chapter transition on this view and subscribes to the page load status.
*/
private fun bindPrevChapterTransition(transition: ChapterTransition.Prev) {
val prevChapter = transition.to
val hasPrevChapter = prevChapter != null
lowerTextView.isVisible = hasPrevChapter
if (hasPrevChapter) {
layout.gravity = Gravity.CENTER_VERTICAL
upperTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_current)) }
append("\n${transition.from.chapter.name}")
}
lowerTextView.text = buildSpannedString {
bold { append(context.getString(R.string.transition_previous)) }
append("\n${prevChapter!!.chapter.name}")
}
} else {
layout.gravity = Gravity.CENTER
upperTextView.text = context.getString(R.string.transition_no_previous)
}
if (prevChapter != null) {
observeStatus(prevChapter, transition)
}
}
/** /**
* Observes the status of the page list of the next/previous chapter. Whenever there's a new * Observes the status of the page list of the next/previous chapter. Whenever there's a new
* state, the pages container is cleaned up before setting the new state. * state, the pages container is cleaned up before setting the new state.

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/upper_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textSize="17.5sp"
tools:text="Top" />
<LinearLayout
android:id="@+id/warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginEnd="8dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_warning_white_24dp"
app:tint="?attr/colorOnBackground"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/warning_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Warning" />
</LinearLayout>
<TextView
android:id="@+id/lower_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="17.5sp"
tools:text="Bottom" />
</LinearLayout>