mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	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
This commit is contained in:
		| @@ -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" | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
|   | ||||
| @@ -90,6 +90,7 @@ class PagerConfig( | ||||
|             4 -> RightAndLeftNavigation() | ||||
|             else -> defaultNavigation() | ||||
|         } | ||||
|         navigationModeChangedListener?.invoke() | ||||
|     } | ||||
|  | ||||
|     enum class ZoomType { | ||||
|   | ||||
| @@ -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() { | ||||
|   | ||||
| @@ -63,5 +63,6 @@ class WebtoonConfig( | ||||
|             4 -> RightAndLeftNavigation() | ||||
|             else -> defaultNavigation() | ||||
|         } | ||||
|         navigationModeChangedListener?.invoke() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|     } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user