Przeglądaj źródła

Add navigation layout overlay (#4683)

* Add navigation layout overlay

* Minor clean up 

Destroy animator when done not on start
Move and change pref title 
Add summary
Andreas 4 lat temu
rodzic
commit
5a7f2684b3

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -79,6 +79,10 @@ object PreferenceKeys {
 
     const val navigationModeWebtoon = "reader_navigation_mode_webtoon"
 
+    const val showNavigationOverlayNewUser = "reader_navigation_overlay_new_user"
+
+    const val showNavigationOverlayOnStart = "reader_navigation_overlay_on_start"
+
     const val webtoonSidePadding = "webtoon_side_padding"
 
     const val portraitColumns = "pref_library_columns_portrait_key"

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -149,6 +149,10 @@ class PreferencesHelper(val context: Context) {
 
     fun navigationModeWebtoon() = flowPrefs.getInt(Keys.navigationModeWebtoon, 0)
 
+    fun showNavigationOverlayNewUser() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUser, true)
+
+    fun showNavigationOverlayOnStart() = flowPrefs.getBoolean(Keys.showNavigationOverlayOnStart, false)
+
     fun portraitColumns() = flowPrefs.getInt(Keys.portraitColumns, 0)
 
     fun landscapeColumns() = flowPrefs.getInt(Keys.landscapeColumns, 0)

+ 140 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt

@@ -0,0 +1,140 @@
+package eu.kanade.tachiyomi.ui.reader
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewPropertyAnimator
+import androidx.core.content.ContextCompat
+import androidx.core.view.isVisible
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
+import kotlin.math.abs
+
+class ReaderNavigationOverlayView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) {
+
+    private var viewPropertyAnimator: ViewPropertyAnimator? = null
+
+    private var navigation: ViewerNavigation? = null
+
+    fun setNavigation(navigation: ViewerNavigation, showOnStart: Boolean) {
+        if (!showOnStart && this.navigation == null) {
+            this.navigation = navigation
+            isVisible = false
+            return
+        }
+
+        this.navigation = navigation
+        invalidate()
+
+        if (isVisible) return
+
+        viewPropertyAnimator = animate()
+            .alpha(1f)
+            .setDuration(1000L)
+            .withStartAction {
+                isVisible = true
+            }
+            .withEndAction {
+                viewPropertyAnimator = null
+            }
+        viewPropertyAnimator?.start()
+    }
+
+    private val textPaint = Paint().apply {
+        textAlign = Paint.Align.CENTER
+        color = Color.WHITE
+        textSize = 64f
+    }
+
+    private val textBorderPaint = Paint().apply {
+        textAlign = Paint.Align.CENTER
+        color = Color.BLACK
+        textSize = 64f
+        style = Paint.Style.STROKE
+        strokeWidth = 8f
+    }
+
+    override fun onDraw(canvas: Canvas?) {
+        if (navigation == null) return
+
+        navigation?.regions?.forEach { region ->
+
+            val paint = paintForRegion(region.type)
+
+            val rect = region.rectF
+
+            canvas?.save()
+
+            // Scale rect from 1f,1f to screen width and height
+            canvas?.scale(width.toFloat(), height.toFloat())
+            canvas?.drawRect(rect, paint)
+
+            canvas?.restore()
+            // Don't want scale anymore because it messes with drawText
+            canvas?.save()
+
+            // Translate origin to rect start (left, top)
+            canvas?.translate((width * rect.left), (height * rect.top))
+
+            // Calculate center of rect width on screen
+            val x = width * (abs(rect.left - rect.right) / 2)
+
+            // Calculate center of rect height on screen
+            val y = height * (abs(rect.top - rect.bottom) / 2)
+
+            canvas?.drawText(region.type.name, x, y, textBorderPaint)
+            canvas?.drawText(region.type.name, x, y, textPaint)
+
+            canvas?.restore()
+        }
+    }
+
+    private fun paintForRegion(type: ViewerNavigation.NavigationRegion): Paint {
+        return Paint().apply {
+            when (type) {
+                ViewerNavigation.NavigationRegion.NEXT -> {
+                    color = ContextCompat.getColor(context, R.color.navigation_next)
+                }
+                ViewerNavigation.NavigationRegion.PREV -> {
+                    color = ContextCompat.getColor(context, R.color.navigation_prev)
+                }
+                ViewerNavigation.NavigationRegion.MENU -> {
+                    color = ContextCompat.getColor(context, R.color.navigation_menu)
+                }
+                ViewerNavigation.NavigationRegion.RIGHT -> {
+                    color = ContextCompat.getColor(context, R.color.navigation_right)
+                }
+                ViewerNavigation.NavigationRegion.LEFT -> {
+                    color = ContextCompat.getColor(context, R.color.navigation_left)
+                }
+            }
+        }
+    }
+
+    override fun performClick(): Boolean {
+        super.performClick()
+
+        if (viewPropertyAnimator == null && isVisible) {
+            viewPropertyAnimator = animate()
+                .alpha(0f)
+                .setDuration(1000L)
+                .withEndAction {
+                    isVisible = false
+                    viewPropertyAnimator = null
+                }
+            viewPropertyAnimator?.start()
+        }
+
+        return true
+    }
+
+    override fun onTouchEvent(event: MotionEvent?): Boolean {
+        // Hide overlay if user start tapping or swiping
+        performClick()
+        return super.onTouchEvent(event)
+    }
+}

+ 14 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt

@@ -15,6 +15,8 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
 
     var imagePropertyChangedListener: (() -> Unit)? = null
 
+    var navigationModeChangedListener: (() -> Unit)? = null
+
     var tappingEnabled = true
     var tappingInverted = TappingInvertMode.NONE
     var longTapEnabled = true
@@ -27,6 +29,10 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
     var navigationMode = 0
         protected set
 
+    var forceNavigationOverlay = false
+
+    var navigationOverlayOnStart = false
+
     var dualPageSplit = false
         protected set
 
@@ -60,6 +66,14 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
 
         preferences.alwaysShowChapterTransition()
             .register({ alwaysShowChapterTransition = it })
+
+        forceNavigationOverlay = preferences.showNavigationOverlayNewUser().get()
+        if (forceNavigationOverlay) {
+            preferences.showNavigationOverlayNewUser().set(false)
+        }
+
+        preferences.showNavigationOverlayOnStart()
+            .register({ navigationOverlayOnStart = it })
     }
 
     protected abstract fun defaultNavigation(): ViewerNavigation

+ 1 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt

@@ -90,6 +90,7 @@ class PagerConfig(
             4 -> RightAndLeftNavigation()
             else -> defaultNavigation()
         }
+        navigationModeChangedListener?.invoke()
     }
 
     enum class ZoomType {

+ 5 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt

@@ -119,6 +119,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
         config.imagePropertyChangedListener = {
             refreshAdapter()
         }
+
+        config.navigationModeChangedListener = {
+            val showOnStart = config.navigationOverlayOnStart || config.forceNavigationOverlay
+            activity.binding.navigationOverlay.setNavigation(config.navigator, showOnStart)
+        }
     }
 
     override fun destroy() {

+ 1 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt

@@ -63,5 +63,6 @@ class WebtoonConfig(
             4 -> RightAndLeftNavigation()
             else -> defaultNavigation()
         }
+        navigationModeChangedListener?.invoke()
     }
 }

+ 5 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt

@@ -136,6 +136,11 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
             refreshAdapter()
         }
 
+        config.navigationModeChangedListener = {
+            val showOnStart = config.navigationOverlayOnStart || config.forceNavigationOverlay
+            activity.binding.navigationOverlay.setNavigation(config.navigator, showOnStart)
+        }
+
         frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
         frame.addView(recycler)
     }

+ 6 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt

@@ -50,6 +50,12 @@ class SettingsReaderController : SettingsController() {
             summaryRes = R.string.pref_show_reading_mode_summary
             defaultValue = true
         }
+        switchPreference {
+            key = Keys.showNavigationOverlayOnStart
+            titleRes = R.string.pref_show_navigation_mode
+            summaryRes = R.string.pref_show_navigation_mode_summary
+            defaultValue = false
+        }
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             switchPreference {
                 key = Keys.trueColor

+ 6 - 0
app/src/main/res/layout/reader_activity.xml

@@ -43,6 +43,12 @@
         android:layout_height="match_parent"
         android:visibility="gone" />
 
+    <eu.kanade.tachiyomi.ui.reader.ReaderNavigationOverlayView
+        android:id="@+id/navigation_overlay"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone" />
+
     <FrameLayout
         android:id="@+id/reader_menu"
         android:layout_width="match_parent"

+ 7 - 0
app/src/main/res/values/colors.xml

@@ -76,4 +76,11 @@
 
     <color name="green">#47a84a</color>
 
+    <!-- Navigation overlay colors -->
+    <color name="navigation_next">#CB84E296</color>
+    <color name="navigation_prev">#CCFF7733</color>
+    <color name="navigation_menu">#CC95818D</color>
+    <color name="navigation_right">#CCA6CFD5</color>
+    <color name="navigation_left">#CC7D1128</color>
+
 </resources>

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -252,6 +252,8 @@
 
       <!-- Reader section -->
     <string name="pref_fullscreen">Fullscreen</string>
+    <string name="pref_show_navigation_mode">Show navigation layout overlay</string>
+    <string name="pref_show_navigation_mode_summary">Show overlay when reader is opened</string>
     <string name="pref_dual_page_split">Dual page split (ALPHA)</string>
     <string name="pref_dual_page_invert">Invert dual page split placement</string>
     <string name="pref_dual_page_invert_summary">If the placement of the dual page split doesn\'t match reading direction</string>