浏览代码

Add orientation toggle to bottom reader menu

arkon 4 年之前
父节点
当前提交
33992d80bf

+ 39 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/OrientationType.kt

@@ -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)
+        }
+    }
+}

+ 34 - 30
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt

@@ -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].
          */

+ 4 - 4
app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt

@@ -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() }
 }
 
 /**

+ 9 - 0
app/src/main/res/drawable/ic_screen_lock_landscape_24dp.xml

@@ -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>

+ 9 - 0
app/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml

@@ -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>

+ 9 - 0
app/src/main/res/drawable/ic_screen_lock_rotation_24dp.xml

@@ -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 - 0
app/src/main/res/drawable/ic_screen_rotation_24dp.xml

@@ -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>

+ 28 - 1
app/src/main/res/layout/reader_activity.xml

@@ -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" />