Add support for margins in Webtoon view

On larger tablets, matching the page width to the screen width in
webtoon mode causes eye strain due to the image looking so magnified.
Adding a page margin to the image can resolve this by effectively
scaling the image down.
This commit is contained in:
John Leehey 2019-11-30 18:37:52 -08:00
parent 80ea9001b3
commit 5b9f362925
12 changed files with 110 additions and 2 deletions

View File

@ -51,6 +51,8 @@ object PreferenceKeys {
const val readWithVolumeKeysInverted = "reader_volume_keys_inverted" const val readWithVolumeKeysInverted = "reader_volume_keys_inverted"
const val webtoonMarginRatio = "margin_ratio"
const val portraitColumns = "pref_library_columns_portrait_key" const val portraitColumns = "pref_library_columns_portrait_key"
const val landscapeColumns = "pref_library_columns_landscape_key" const val landscapeColumns = "pref_library_columns_landscape_key"

View File

@ -79,6 +79,8 @@ class PreferencesHelper(val context: Context) {
fun readWithVolumeKeysInverted() = rxPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false) fun readWithVolumeKeysInverted() = rxPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false)
fun marginRatio() = rxPrefs.getInteger(Keys.webtoonMarginRatio, 0)
fun portraitColumns() = rxPrefs.getInteger(Keys.portraitColumns, 0) fun portraitColumns() = rxPrefs.getInteger(Keys.portraitColumns, 0)
fun landscapeColumns() = rxPrefs.getInteger(Keys.landscapeColumns, 0) fun landscapeColumns() = rxPrefs.getInteger(Keys.landscapeColumns, 0)

View File

@ -82,6 +82,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDia
private fun initWebtoonPreferences() { private fun initWebtoonPreferences() {
webtoon_prefs_group.visible() webtoon_prefs_group.visible()
crop_borders_webtoon.bindToPreference(preferences.cropBordersWebtoon()) crop_borders_webtoon.bindToPreference(preferences.cropBordersWebtoon())
margin_ratio_webtoon.bindToPreference(preferences.marginRatio())
} }
/** /**

View File

@ -34,6 +34,9 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) {
var doubleTapAnimDuration = 500 var doubleTapAnimDuration = 500
private set private set
var marginRatio = 0f
private set
init { init {
preferences.readWithTapping() preferences.readWithTapping()
.register({ tappingEnabled = it }) .register({ tappingEnabled = it })
@ -52,6 +55,23 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) {
preferences.readWithVolumeKeysInverted() preferences.readWithVolumeKeysInverted()
.register({ volumeKeysInverted = it }) .register({ volumeKeysInverted = it })
preferences.marginRatio()
.register({ marginFromPreference(it) }, { imagePropertyChangedListener?.invoke() })
}
private fun marginFromPreference(position: Int) {
marginRatio = when (position) {
1 -> PageMargin.TEN_PERCENT
2 -> PageMargin.TWENTY_FIVE_PERCENT
else -> PageMargin.NO_MARGIN
}
}
object PageMargin {
const val NO_MARGIN = 0f
const val TEN_PERCENT = 0.1f
const val TWENTY_FIVE_PERCENT = 0.25f
} }
fun unsubscribe() { fun unsubscribe() {

View File

@ -2,11 +2,13 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.support.v7.widget.AppCompatButton import android.support.v7.widget.AppCompatButton
import android.support.v7.widget.AppCompatImageView import android.support.v7.widget.AppCompatImageView
import android.view.Gravity import android.view.Gravity
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
@ -111,7 +113,7 @@ class WebtoonPageHolder(
private var readImageHeaderSubscription: Subscription? = null private var readImageHeaderSubscription: Subscription? = null
init { init {
frame.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT) refreshLayoutParams()
} }
/** /**
@ -120,6 +122,15 @@ class WebtoonPageHolder(
fun bind(page: ReaderPage) { fun bind(page: ReaderPage) {
this.page = page this.page = page
observeStatus() observeStatus()
refreshLayoutParams()
}
private fun refreshLayoutParams() {
frame.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
val margin = Resources.getSystem().displayMetrics.widthPixels * viewer.config.marginRatio
marginEnd = margin.toInt()
marginStart = margin.toInt()
}
} }
/** /**

View File

@ -110,6 +110,8 @@ class WebtoonViewer(val activity: ReaderActivity) : BaseViewer {
frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT) frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
frame.addView(recycler) frame.addView(recycler)
config.imagePropertyChangedListener = { adapter.notifyDataSetChanged() }
} }
/** /**

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.setting
import android.support.graphics.drawable.VectorDrawableCompat import android.support.graphics.drawable.VectorDrawableCompat
import android.support.v4.graphics.drawable.DrawableCompat import android.support.v4.graphics.drawable.DrawableCompat
import android.support.v7.preference.* import android.support.v7.preference.*
import eu.kanade.tachiyomi.widget.preference.FloatListPreference
import eu.kanade.tachiyomi.widget.preference.IntListPreference import eu.kanade.tachiyomi.widget.preference.IntListPreference
@DslMarker @DslMarker
@ -37,6 +38,10 @@ inline fun PreferenceGroup.intListPreference(block: (@DSL IntListPreference).()
return initThenAdd(IntListPreference(context), block).also(::initDialog) return initThenAdd(IntListPreference(context), block).also(::initDialog)
} }
inline fun PreferenceGroup.floatListPreference(block: (@DSL FloatListPreference).() -> Unit): FloatListPreference {
return initThenAdd(FloatListPreference(context), block).also(::initDialog)
}
inline fun PreferenceGroup.multiSelectListPreference(block: (@DSL MultiSelectListPreference).() -> Unit): MultiSelectListPreference { inline fun PreferenceGroup.multiSelectListPreference(block: (@DSL MultiSelectListPreference).() -> Unit): MultiSelectListPreference {
return initThenAdd(MultiSelectListPreference(context), block).also(::initDialog) return initThenAdd(MultiSelectListPreference(context), block).also(::initDialog)
} }

View File

@ -112,6 +112,16 @@ class SettingsReaderController : SettingsController() {
titleRes = R.string.pref_crop_borders titleRes = R.string.pref_crop_borders
defaultValue = false defaultValue = false
} }
floatListPreference {
key = Keys.webtoonMarginRatio
titleRes = R.string.pref_reader_theme
entriesRes = arrayOf(R.string.webtoon_margin_ratio_0,
R.string.webtoon_margin_ratio_10, R.string.webtoon_margin_ratio_25)
entryValues = arrayOf("0", "1", "2")
defaultValue = "0"
summary = "%s"
}
} }
preferenceCategory { preferenceCategory {
titleRes = R.string.pref_reader_navigation titleRes = R.string.pref_reader_navigation

View File

@ -0,0 +1,26 @@
package eu.kanade.tachiyomi.widget.preference
import android.content.Context
import android.support.v7.preference.ListPreference
import android.util.AttributeSet
class FloatListPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
ListPreference(context, attrs) {
override fun persistString(value: String?): Boolean {
return value != null && persistFloat(value.toFloat())
}
override fun getPersistedString(defaultReturnValue: String?): String? {
// When the underlying preference is using a PreferenceDataStore, there's no way (for now)
// to check if a value is in the store, so we use a most likely unused value as workaround
val defaultIntValue = Float.NEGATIVE_INFINITY
val value = getPersistedFloat(defaultIntValue)
return if (value != defaultIntValue) {
value.toString()
} else {
defaultReturnValue
}
}
}

View File

@ -240,6 +240,25 @@
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
app:layout_constraintTop_toBottomOf="@id/webtoon_prefs" /> app:layout_constraintTop_toBottomOf="@id/webtoon_prefs" />
<TextView
android:id="@+id/margin_ratio_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/pref_reader_margin"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/verticalcenter"
app:layout_constraintBaseline_toBaselineOf="@id/margin_ratio_webtoon"/>
<android.support.v7.widget.AppCompatSpinner
android:id="@+id/margin_ratio_webtoon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:entries="@array/margin_ratio"
app:layout_constraintLeft_toRightOf="@id/verticalcenter"
app:layout_constraintRight_toRightOf="@id/spinner_end"
app:layout_constraintTop_toBottomOf="@id/crop_borders_webtoon"/>
<!-- Groups of preferences --> <!-- Groups of preferences -->
<android.support.constraint.Group <android.support.constraint.Group
@ -255,7 +274,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" android:visibility="gone"
app:constraint_referenced_ids="webtoon_prefs,crop_borders_webtoon" /> app:constraint_referenced_ids="webtoon_prefs,crop_borders_webtoon,margin_ratio_text,margin_ratio_webtoon" />
<android.support.constraint.Guideline <android.support.constraint.Guideline
android:id="@+id/verticalcenter" android:id="@+id/verticalcenter"

View File

@ -53,6 +53,12 @@
<item>@string/scale_type_smart_fit</item> <item>@string/scale_type_smart_fit</item>
</string-array> </string-array>
<string-array name="margin_ratio">
<item>@string/webtoon_margin_ratio_0</item>
<item>@string/webtoon_margin_ratio_10</item>
<item>@string/webtoon_margin_ratio_25</item>
</string-array>
<string-array name="image_scale_type_values"> <string-array name="image_scale_type_values">
<item>1</item> <item>1</item>
<item>2</item> <item>2</item>

View File

@ -196,6 +196,7 @@
<string name="pref_read_with_tapping">Tapping</string> <string name="pref_read_with_tapping">Tapping</string>
<string name="pref_read_with_long_tap">Long tap dialog</string> <string name="pref_read_with_long_tap">Long tap dialog</string>
<string name="pref_reader_theme">Background color</string> <string name="pref_reader_theme">Background color</string>
<string name="pref_reader_margin">Margin ratio</string>
<string name="white_background">White</string> <string name="white_background">White</string>
<string name="black_background">Black</string> <string name="black_background">Black</string>
<string name="pref_viewer_type">Default viewer</string> <string name="pref_viewer_type">Default viewer</string>
@ -230,6 +231,9 @@
<string name="color_filter_g_value">G</string> <string name="color_filter_g_value">G</string>
<string name="color_filter_b_value">B</string> <string name="color_filter_b_value">B</string>
<string name="color_filter_a_value">A</string> <string name="color_filter_a_value">A</string>
<string name="webtoon_margin_ratio_0">No margin</string>
<string name="webtoon_margin_ratio_10">10%</string>
<string name="webtoon_margin_ratio_25">25%</string>
<!-- Downloads section --> <!-- Downloads section -->