Add orientation toggle to bottom reader menu

This commit is contained in:
arkon 2021-02-13 18:50:50 -05:00
parent a92b0e567b
commit 33992d80bf
8 changed files with 141 additions and 35 deletions

View file

@ -0,0 +1,39 @@
package eu.kanade.tachiyomi.ui.reader
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.content.res.Resources
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import kotlin.math.max
enum class OrientationType(val prefValue: Int, val flag: Int, @StringRes val stringRes: Int, @DrawableRes val iconRes: Int) {
FREE(1, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, R.string.rotation_free, R.drawable.ic_screen_rotation_24dp),
LOCKED_PORTRAIT(2, ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, R.string.rotation_lock, R.drawable.ic_screen_lock_rotation_24dp),
LOCKED_LANDSCAPE(2, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, R.string.rotation_lock, R.drawable.ic_screen_lock_rotation_24dp),
PORTRAIT(3, ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, R.string.rotation_force_portrait, R.drawable.ic_screen_lock_portrait_24dp),
LANDSCAPE(4, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, R.string.rotation_force_landscape, R.drawable.ic_screen_lock_landscape_24dp);
companion object {
fun fromPreference(preference: Int, resources: Resources): OrientationType = when (preference) {
2 -> {
val currentOrientation = resources.configuration.orientation
if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
LOCKED_PORTRAIT
} else {
LOCKED_LANDSCAPE
}
}
3 -> PORTRAIT
4 -> LANDSCAPE
else -> FREE
}
fun getNextOrientation(preference: Int, resources: Resources): OrientationType {
// There's only 4 options (1 to 4)
val newOrientation = max(1, (preference + 1) % 5)
return fromPreference(newOrientation, resources)
}
}
}

View file

@ -6,8 +6,6 @@ import android.app.ProgressDialog
import android.content.ClipData
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Build
@ -21,6 +19,7 @@ import android.view.WindowManager
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.SeekBar
import android.widget.Toast
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
@ -111,6 +110,8 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
@Suppress("DEPRECATION")
private var progressDialog: ProgressDialog? = null
private var rotationToast: Toast? = null
companion object {
@Suppress("unused")
const val LEFT_TO_RIGHT = 1
@ -344,6 +345,21 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
}
}
binding.actionRotation.setOnClickListener {
val newOrientation = OrientationType.getNextOrientation(preferences.rotation().get(), resources)
preferences.rotation().set(newOrientation.prefValue)
setOrientation(newOrientation.flag)
rotationToast?.cancel()
rotationToast = toast(newOrientation.stringRes)
}
preferences.rotation().asImmediateFlow { updateRotationShortcut(it) }
.onEach {
updateRotationShortcut(it)
}
.launchIn(lifecycleScope)
binding.actionCustomFilter.setOnClickListener {
val sheet = ReaderColorFilterSheet(this)
// Remove dimmed backdrop so changes can be previewed
@ -363,6 +379,11 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
setMenuVisibility(menuVisible)
}
private fun updateRotationShortcut(preference: Int) {
val orientation = OrientationType.fromPreference(preference, resources)
binding.actionRotation.setImageResource(orientation.iconRes)
}
/**
* Sets the visibility of the menu according to [visible] and with an optional parameter to
* [animate] the views.
@ -382,7 +403,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
toolbarAnimation.setAnimationListener(
object : SimpleAnimationListener() {
override fun onAnimationStart(animation: Animation) {
// Fix status bar being translucent the first time it's opened.
// Fix status bar being translucent the first time it's opened.
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
}
}
@ -668,6 +689,16 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
)
}
/**
* Forces the user preferred [orientation] on the activity.
*/
private fun setOrientation(orientation: Int) {
val newOrientation = OrientationType.fromPreference(orientation, resources)
if (newOrientation.flag != requestedOrientation) {
requestedOrientation = newOrientation.flag
}
}
/**
* Class that handles the user preferences of the reader.
*/
@ -721,33 +752,6 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
.launchIn(lifecycleScope)
}
/**
* Forces the user preferred [orientation] on the activity.
*/
private fun setOrientation(orientation: Int) {
val newOrientation = when (orientation) {
// Lock in current orientation
2 -> {
val currentOrientation = resources.configuration.orientation
if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
} else {
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
}
}
// Lock in portrait
3 -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
// Lock in landscape
4 -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
// Rotation free
else -> ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
if (newOrientation != requestedOrientation) {
requestedOrientation = newOrientation
}
}
/**
* Sets the visibility of the bottom page indicator according to [visible].
*/

View file

@ -42,8 +42,8 @@ import kotlin.math.roundToInt
* @param resource the text resource.
* @param duration the duration of the toast. Defaults to short.
*/
fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, resource, duration).show()
fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT): Toast {
return Toast.makeText(this, resource, duration).also { it.show() }
}
/**
@ -52,8 +52,8 @@ fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT)
* @param text the text to display.
* @param duration the duration of the toast. Defaults to short.
*/
fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, text.orEmpty(), duration).show()
fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT): Toast {
return Toast.makeText(this, text.orEmpty(), duration).also { it.show() }
}
/**

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/black"
android:pathData="M21,5L3,5c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,7c0,-1.1 -0.9,-2 -2,-2zM19,17L5,17L5,7h14v10zM10,16h4c0.55,0 1,-0.45 1,-1v-3c0,-0.55 -0.45,-1 -1,-1v-1c0,-1.11 -0.9,-2 -2,-2 -1.11,0 -2,0.9 -2,2v1c-0.55,0 -1,0.45 -1,1v3c0,0.55 0.45,1 1,1zM10.8,10c0,-0.66 0.54,-1.2 1.2,-1.2 0.66,0 1.2,0.54 1.2,1.2v1h-2.4v-1z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/black"
android:pathData="M10,16h4c0.55,0 1,-0.45 1,-1v-3c0,-0.55 -0.45,-1 -1,-1v-1c0,-1.11 -0.9,-2 -2,-2 -1.11,0 -2,0.9 -2,2v1c-0.55,0 -1,0.45 -1,1v3c0,0.55 0.45,1 1,1zM10.8,10c0,-0.66 0.54,-1.2 1.2,-1.2 0.66,0 1.2,0.54 1.2,1.2v1h-2.4v-1zM17,1L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-2 -2,-2zM17,19L7,19L7,5h10v14z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/black"
android:pathData="M23.25,12.77l-2.57,-2.57 -1.41,1.41 2.22,2.22 -5.66,5.66L4.51,8.17l5.66,-5.66 2.1,2.1 1.41,-1.41L11.23,0.75c-0.59,-0.59 -1.54,-0.59 -2.12,0L2.75,7.11c-0.59,0.59 -0.59,1.54 0,2.12l12.02,12.02c0.59,0.59 1.54,0.59 2.12,0l6.36,-6.36c0.59,-0.59 0.59,-1.54 0,-2.12zM8.47,20.48C5.2,18.94 2.86,15.76 2.5,12L1,12c0.51,6.16 5.66,11 11.95,11l0.66,-0.03 -3.81,-3.82 -1.33,1.33zM16,9h5c0.55,0 1,-0.45 1,-1L22,4c0,-0.55 -0.45,-1 -1,-1v-0.5C21,1.12 19.88,0 18.5,0S16,1.12 16,2.5L16,3c-0.55,0 -1,0.45 -1,1v4c0,0.55 0.45,1 1,1zM16.8,2.5c0,-0.94 0.76,-1.7 1.7,-1.7s1.7,0.76 1.7,1.7L20.2,3h-3.4v-0.5z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/black"
android:pathData="M16.48,2.52c3.27,1.55 5.61,4.72 5.97,8.48h1.5C23.44,4.84 18.29,0 12,0l-0.66,0.03 3.81,3.81 1.33,-1.32zM10.23,1.75c-0.59,-0.59 -1.54,-0.59 -2.12,0L1.75,8.11c-0.59,0.59 -0.59,1.54 0,2.12l12.02,12.02c0.59,0.59 1.54,0.59 2.12,0l6.36,-6.36c0.59,-0.59 0.59,-1.54 0,-2.12L10.23,1.75zM14.83,21.19L2.81,9.17l6.36,-6.36 12.02,12.02 -6.36,6.36zM7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32z" />
</vector>

View file

@ -145,6 +145,33 @@
android:layout_gravity="bottom"
android:background="?attr/colorPrimary">
<!-- <ImageButton-->
<!-- android:id="@+id/action_reader_mode"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="match_parent"-->
<!-- android:background="?selectableItemBackgroundBorderless"-->
<!-- android:contentDescription="@string/viewer"-->
<!-- android:padding="@dimen/material_layout_keylines_screen_edge_margin"-->
<!-- app:layout_constraintEnd_toStartOf="@id/action_rotation"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"-->
<!-- app:srcCompat="@drawable/ic_book_24dp"-->
<!-- app:tint="?attr/colorOnPrimary" />-->
<!-- app:layout_constraintStart_toEndOf="@+id/action_reader_mode" -->
<ImageButton
android:id="@+id/action_rotation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/pref_rotation_type"
android:padding="@dimen/material_layout_keylines_screen_edge_margin"
app:layout_constraintEnd_toStartOf="@id/action_custom_filter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_screen_rotation_24dp"
app:tint="?attr/colorOnPrimary" />
<ImageButton
android:id="@+id/action_custom_filter"
android:layout_width="wrap_content"
@ -153,7 +180,7 @@
android:contentDescription="@string/custom_filter"
android:padding="@dimen/material_layout_keylines_screen_edge_margin"
app:layout_constraintEnd_toStartOf="@id/action_settings"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@+id/action_rotation"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_brightness_4_24dp"
app:tint="?attr/colorOnPrimary" />