mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 05:31:51 +01:00
Add orientation toggle to bottom reader menu
This commit is contained in:
parent
a92b0e567b
commit
33992d80bf
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,8 +6,6 @@ import android.app.ProgressDialog
|
|||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@ -21,6 +19,7 @@ import android.view.WindowManager
|
|||||||
import android.view.animation.Animation
|
import android.view.animation.Animation
|
||||||
import android.view.animation.AnimationUtils
|
import android.view.animation.AnimationUtils
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
@ -111,6 +110,8 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
|||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
private var progressDialog: ProgressDialog? = null
|
private var progressDialog: ProgressDialog? = null
|
||||||
|
|
||||||
|
private var rotationToast: Toast? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
const val LEFT_TO_RIGHT = 1
|
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 {
|
binding.actionCustomFilter.setOnClickListener {
|
||||||
val sheet = ReaderColorFilterSheet(this)
|
val sheet = ReaderColorFilterSheet(this)
|
||||||
// Remove dimmed backdrop so changes can be previewed
|
// Remove dimmed backdrop so changes can be previewed
|
||||||
@ -363,6 +379,11 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
|||||||
setMenuVisibility(menuVisible)
|
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
|
* Sets the visibility of the menu according to [visible] and with an optional parameter to
|
||||||
* [animate] the views.
|
* [animate] the views.
|
||||||
@ -382,7 +403,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
|||||||
toolbarAnimation.setAnimationListener(
|
toolbarAnimation.setAnimationListener(
|
||||||
object : SimpleAnimationListener() {
|
object : SimpleAnimationListener() {
|
||||||
override fun onAnimationStart(animation: Animation) {
|
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)
|
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.
|
* Class that handles the user preferences of the reader.
|
||||||
*/
|
*/
|
||||||
@ -721,33 +752,6 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
|||||||
.launchIn(lifecycleScope)
|
.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].
|
* Sets the visibility of the bottom page indicator according to [visible].
|
||||||
*/
|
*/
|
||||||
|
@ -42,8 +42,8 @@ import kotlin.math.roundToInt
|
|||||||
* @param resource the text resource.
|
* @param resource the text resource.
|
||||||
* @param duration the duration of the toast. Defaults to short.
|
* @param duration the duration of the toast. Defaults to short.
|
||||||
*/
|
*/
|
||||||
fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT) {
|
fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT): Toast {
|
||||||
Toast.makeText(this, resource, duration).show()
|
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 text the text to display.
|
||||||
* @param duration the duration of the toast. Defaults to short.
|
* @param duration the duration of the toast. Defaults to short.
|
||||||
*/
|
*/
|
||||||
fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT) {
|
fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT): Toast {
|
||||||
Toast.makeText(this, text.orEmpty(), duration).show()
|
return Toast.makeText(this, text.orEmpty(), duration).also { it.show() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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>
|
@ -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>
|
@ -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>
|
9
app/src/main/res/drawable/ic_screen_rotation_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_screen_rotation_24dp.xml
Normal 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>
|
@ -145,6 +145,33 @@
|
|||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:background="?attr/colorPrimary">
|
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
|
<ImageButton
|
||||||
android:id="@+id/action_custom_filter"
|
android:id="@+id/action_custom_filter"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -153,7 +180,7 @@
|
|||||||
android:contentDescription="@string/custom_filter"
|
android:contentDescription="@string/custom_filter"
|
||||||
android:padding="@dimen/material_layout_keylines_screen_edge_margin"
|
android:padding="@dimen/material_layout_keylines_screen_edge_margin"
|
||||||
app:layout_constraintEnd_toStartOf="@id/action_settings"
|
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:layout_constraintTop_toTopOf="parent"
|
||||||
app:srcCompat="@drawable/ic_brightness_4_24dp"
|
app:srcCompat="@drawable/ic_brightness_4_24dp"
|
||||||
app:tint="?attr/colorOnPrimary" />
|
app:tint="?attr/colorOnPrimary" />
|
||||||
|
Loading…
Reference in New Issue
Block a user