mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
feat: Cutout support on pre-Android P
This commit is contained in:
parent
afe3fd64af
commit
9644b71e57
8 changed files with 119 additions and 71 deletions
|
@ -6,4 +6,9 @@
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
-->
|
-->
|
||||||
|
## Additions
|
||||||
|
- Added cutout support for some pre-Android P devices
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed cutout behaviour for Android P
|
|
@ -76,6 +76,7 @@ class ReaderGeneralView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePrefs() {
|
private fun updatePrefs() {
|
||||||
binding.cutoutShort.isVisible = DeviceUtil.hasCutout(context) && preferences.fullscreen().get()
|
binding.cutoutShort.isVisible =
|
||||||
|
DeviceUtil.hasCutout(context as ReaderActivity).ordinal >= DeviceUtil.CutoutSupport.MODERN.ordinal && preferences.fullscreen().get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,9 @@ package eu.kanade.tachiyomi.ui.reader.settings
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.hardware.display.DisplayManager
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.Display
|
|
||||||
import androidx.core.content.getSystemService
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import dev.yokai.domain.ui.settings.ReaderPreferences
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.databinding.ReaderPagedLayoutBinding
|
import eu.kanade.tachiyomi.databinding.ReaderPagedLayoutBinding
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
|
@ -18,7 +13,6 @@ import eu.kanade.tachiyomi.util.bindToPreference
|
||||||
import eu.kanade.tachiyomi.util.lang.addBetaTag
|
import eu.kanade.tachiyomi.util.lang.addBetaTag
|
||||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||||
import eu.kanade.tachiyomi.widget.BaseReaderSettingsView
|
import eu.kanade.tachiyomi.widget.BaseReaderSettingsView
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
|
|
||||||
class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
BaseReaderSettingsView<ReaderPagedLayoutBinding>(context, attrs) {
|
BaseReaderSettingsView<ReaderPagedLayoutBinding>(context, attrs) {
|
||||||
|
@ -110,15 +104,15 @@ class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: Attribu
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
val ogView = (context as? Activity)?.window?.decorView
|
val ogView = (context as? Activity)?.window?.decorView
|
||||||
val hasCutout = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
||||||
ogView?.rootWindowInsets?.displayCutout?.safeInsetTop != null || ogView?.rootWindowInsets?.displayCutout?.safeInsetBottom != null
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
binding.landscapeZoom.isVisible = show && preferences.imageScaleType().get() == SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE
|
binding.landscapeZoom.isVisible = show && preferences.imageScaleType().get() == SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE
|
||||||
binding.extendPastCutout.isVisible = show && isFullFit && hasCutout && preferences.fullscreen().get()
|
binding.extendPastCutout.isVisible =
|
||||||
binding.extendPastCutoutLandscape.isVisible = DeviceUtil.hasCutout(context) && preferences.fullscreen().get() &&
|
show && isFullFit
|
||||||
ogView?.resources?.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE
|
&& DeviceUtil.hasCutout(context as? Activity).ordinal >= DeviceUtil.CutoutSupport.LEGACY.ordinal
|
||||||
|
&& preferences.fullscreen().get()
|
||||||
|
binding.extendPastCutoutLandscape.isVisible =
|
||||||
|
DeviceUtil.hasCutout(context as? Activity).ordinal >= DeviceUtil.CutoutSupport.MODERN.ordinal
|
||||||
|
&& preferences.fullscreen().get()
|
||||||
|
&& ogView?.resources?.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
if (binding.extendPastCutoutLandscape.isVisible) {
|
if (binding.extendPastCutoutLandscape.isVisible) {
|
||||||
binding.filterLinearLayout.removeView(binding.extendPastCutoutLandscape)
|
binding.filterLinearLayout.removeView(binding.extendPastCutoutLandscape)
|
||||||
binding.filterLinearLayout.addView(
|
binding.filterLinearLayout.addView(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.reader.viewer
|
package eu.kanade.tachiyomi.ui.reader.viewer
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
|
@ -16,7 +17,6 @@ import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.annotation.StyleRes
|
import androidx.annotation.StyleRes
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import coil.dispose
|
import coil.dispose
|
||||||
import coil.imageLoader
|
import coil.imageLoader
|
||||||
|
@ -29,6 +29,7 @@ import com.github.chrisbanes.photoview.PhotoView
|
||||||
import dev.yokai.domain.ui.settings.ReaderPreferences.CutoutBehaviour
|
import dev.yokai.domain.ui.settings.ReaderPreferences.CutoutBehaviour
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonSubsamplingImageView
|
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonSubsamplingImageView
|
||||||
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||||
import eu.kanade.tachiyomi.util.system.animatorDurationScale
|
import eu.kanade.tachiyomi.util.system.animatorDurationScale
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
@ -190,15 +191,16 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
||||||
config.insetInfo.scaleTypeIsFullFit && topInsets + bottomInsets > 0,
|
config.insetInfo.scaleTypeIsFullFit && topInsets + bottomInsets > 0,
|
||||||
)
|
)
|
||||||
if ((config.insetInfo.cutoutBehavior != CutoutBehaviour.IGNORE || !config.insetInfo.scaleTypeIsFullFit) &&
|
if ((config.insetInfo.cutoutBehavior != CutoutBehaviour.IGNORE || !config.insetInfo.scaleTypeIsFullFit) &&
|
||||||
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q &&
|
|
||||||
config.insetInfo.isFullscreen
|
config.insetInfo.isFullscreen
|
||||||
) {
|
) {
|
||||||
val insets: WindowInsets? = config.insetInfo.insets
|
val insets: WindowInsets? = config.insetInfo.insets
|
||||||
setExtraSpace(
|
setExtraSpace(
|
||||||
0f,
|
0f,
|
||||||
insets?.displayCutout?.boundingRectTop?.height()?.toFloat() ?: 0f,
|
DeviceUtil.getCutoutHeight(context as? Activity, config.insetInfo.cutoutSupport).toFloat(),
|
||||||
0f,
|
0f,
|
||||||
insets?.displayCutout?.boundingRectBottom?.height()?.toFloat() ?: 0f,
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q)
|
||||||
|
insets?.displayCutout?.boundingRectBottom?.height()?.toFloat() ?: 0f
|
||||||
|
else 0f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,6 +320,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
data class InsetInfo(
|
data class InsetInfo(
|
||||||
|
val cutoutSupport: DeviceUtil.CutoutSupport,
|
||||||
val cutoutBehavior: CutoutBehaviour,
|
val cutoutBehavior: CutoutBehaviour,
|
||||||
val topCutoutInset: Float,
|
val topCutoutInset: Float,
|
||||||
val bottomCutoutInset: Float,
|
val bottomCutoutInset: Float,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.ui.reader.viewer.navigation.EdgeNavigation
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.KindlishNavigation
|
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.KindlishNavigation
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation
|
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.RightAndLeftNavigation
|
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.RightAndLeftNavigation
|
||||||
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
|
|
@ -26,6 +26,7 @@ import eu.kanade.tachiyomi.ui.reader.viewer.ReaderErrorView
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig.ZoomType
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig.ZoomType
|
||||||
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.system.ImageUtil.isPagePadded
|
import eu.kanade.tachiyomi.util.system.ImageUtil.isPagePadded
|
||||||
import eu.kanade.tachiyomi.util.system.ThemeUtil
|
import eu.kanade.tachiyomi.util.system.ThemeUtil
|
||||||
|
@ -543,12 +544,13 @@ class PagerPageHolder(
|
||||||
zoomStartPosition = viewer.config.imageZoomType,
|
zoomStartPosition = viewer.config.imageZoomType,
|
||||||
landscapeZoom = viewer.config.landscapeZoom,
|
landscapeZoom = viewer.config.landscapeZoom,
|
||||||
insetInfo = InsetInfo(
|
insetInfo = InsetInfo(
|
||||||
|
cutoutSupport = DeviceUtil.hasCutout(viewer.activity),
|
||||||
cutoutBehavior = viewer.config.cutoutBehavior,
|
cutoutBehavior = viewer.config.cutoutBehavior,
|
||||||
topCutoutInset = viewer.activity.window.decorView.rootWindowInsets?.topCutoutInset()?.toFloat() ?: 0f,
|
topCutoutInset = viewer.activity.window.decorView.rootWindowInsets?.topCutoutInset()?.toFloat() ?: 0f,
|
||||||
bottomCutoutInset = viewer.activity.window.decorView.rootWindowInsets?.bottomCutoutInset()?.toFloat() ?: 0f,
|
bottomCutoutInset = viewer.activity.window.decorView.rootWindowInsets?.bottomCutoutInset()?.toFloat() ?: 0f,
|
||||||
scaleTypeIsFullFit = viewer.config.scaleTypeIsFullFit(),
|
scaleTypeIsFullFit = viewer.config.scaleTypeIsFullFit(),
|
||||||
isFullscreen = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
|
isFullscreen = viewer.config.isFullscreen
|
||||||
viewer.config.isFullscreen && !viewer.activity.isInMultiWindowMode,
|
&& if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) !viewer.activity.isInMultiWindowMode else true,
|
||||||
isSplitScreen = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && viewer.activity.isInMultiWindowMode,
|
isSplitScreen = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && viewer.activity.isInMultiWindowMode,
|
||||||
insets = viewer.activity.window.decorView.rootWindowInsets,
|
insets = viewer.activity.window.decorView.rootWindowInsets,
|
||||||
),
|
),
|
||||||
|
|
|
@ -121,7 +121,9 @@ class SettingsReaderController : SettingsController() {
|
||||||
// FIXME: Transition from reader to homepage is broken when cutout short is disabled
|
// FIXME: Transition from reader to homepage is broken when cutout short is disabled
|
||||||
title = context.getString(R.string.pref_cutout_short).addBetaTag(context)
|
title = context.getString(R.string.pref_cutout_short).addBetaTag(context)
|
||||||
|
|
||||||
preferences.fullscreen().changesIn(viewScope) { isVisible = DeviceUtil.hasCutout(activity) && it}
|
preferences.fullscreen().changesIn(viewScope) {
|
||||||
|
isVisible = DeviceUtil.hasCutout(activity).ordinal >= DeviceUtil.CutoutSupport.MODERN.ordinal && it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
listPreference(activity) {
|
listPreference(activity) {
|
||||||
bindTo(readerPreferences.landscapeCutoutBehavior())
|
bindTo(readerPreferences.landscapeCutoutBehavior())
|
||||||
|
@ -130,7 +132,9 @@ class SettingsReaderController : SettingsController() {
|
||||||
entriesRes = values.map { it.titleResId }.toTypedArray()
|
entriesRes = values.map { it.titleResId }.toTypedArray()
|
||||||
entryValues = values.map { it.name }
|
entryValues = values.map { it.name }
|
||||||
|
|
||||||
preferences.fullscreen().changesIn(viewScope) { isVisible = DeviceUtil.hasCutout(activity) && it}
|
preferences.fullscreen().changesIn(viewScope) {
|
||||||
|
isVisible = DeviceUtil.hasCutout(activity).ordinal >= DeviceUtil.CutoutSupport.MODERN.ordinal && it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switchPreference {
|
switchPreference {
|
||||||
key = Keys.keepScreenOn
|
key = Keys.keepScreenOn
|
||||||
|
@ -221,22 +225,13 @@ class SettingsReaderController : SettingsController() {
|
||||||
entryValues = values.map { it.name }
|
entryValues = values.map { it.name }
|
||||||
|
|
||||||
// Calling this once to show only on cutout
|
// Calling this once to show only on cutout
|
||||||
isVisible = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
isVisible = DeviceUtil.hasCutout(activity).ordinal >= DeviceUtil.CutoutSupport.LEGACY.ordinal
|
||||||
activityBinding?.root?.rootWindowInsets?.displayCutout?.safeInsetTop != null ||
|
|
||||||
activityBinding?.root?.rootWindowInsets?.displayCutout?.safeInsetBottom != null
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
// Calling this a second time in case activity is recreated while on this page
|
// Calling this a second time in case activity is recreated while on this page
|
||||||
// Keep the first so it shouldn't animate hiding the preference for phones without
|
// Keep the first so it shouldn't animate hiding the preference for phones without
|
||||||
// cutouts
|
// cutouts
|
||||||
activityBinding?.root?.post {
|
activityBinding?.root?.post {
|
||||||
isVisible = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
isVisible = DeviceUtil.hasCutout(activity).ordinal >= DeviceUtil.CutoutSupport.LEGACY.ordinal
|
||||||
activityBinding?.root?.rootWindowInsets?.displayCutout?.safeInsetTop != null ||
|
|
||||||
activityBinding?.root?.rootWindowInsets?.displayCutout?.safeInsetBottom != null
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
package eu.kanade.tachiyomi.util.system
|
package eu.kanade.tachiyomi.util.system
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.app.Activity
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.Display
|
import android.view.Display
|
||||||
import android.view.View
|
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.view.WindowManager
|
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
object DeviceUtil {
|
object DeviceUtil {
|
||||||
|
|
||||||
|
@ -92,59 +94,104 @@ object DeviceUtil {
|
||||||
fun setLegacyCutoutMode(window: Window, mode: LegacyCutoutMode) {
|
fun setLegacyCutoutMode(window: Window, mode: LegacyCutoutMode) {
|
||||||
when (mode) {
|
when (mode) {
|
||||||
LegacyCutoutMode.SHORT_EDGES -> {
|
LegacyCutoutMode.SHORT_EDGES -> {
|
||||||
/* Deprecated method
|
// Vivo doesn't support this, user had to set it from Settings
|
||||||
|
/*
|
||||||
if (isVivo) {
|
if (isVivo) {
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
|
||||||
var systemUiVisibility = window.decorView.systemUiVisibility
|
|
||||||
systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
||||||
systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
||||||
window.decorView.systemUiVisibility = systemUiVisibility
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
LegacyCutoutMode.NEVER -> {
|
LegacyCutoutMode.NEVER -> {
|
||||||
/* Deprecated method
|
// Vivo doesn't support this, user had to set it from Settings
|
||||||
|
/*
|
||||||
if (isVivo) {
|
if (isVivo) {
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
|
||||||
var systemUiVisibility = window.decorView.systemUiVisibility
|
|
||||||
systemUiVisibility = systemUiVisibility and View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN.inv()
|
|
||||||
systemUiVisibility = systemUiVisibility and View.SYSTEM_UI_FLAG_LAYOUT_STABLE.inv()
|
|
||||||
window.decorView.systemUiVisibility = systemUiVisibility
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasCutout(context: Context? = null): Boolean {
|
fun hasCutout(context: Activity?): CutoutSupport {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (context?.getSystemService<DisplayManager>()
|
||||||
return context?.getSystemService<DisplayManager>()
|
?.getDisplay(Display.DEFAULT_DISPLAY)?.cutout != null)
|
||||||
?.getDisplay(Display.DEFAULT_DISPLAY)?.cutout != null
|
return CutoutSupport.EXTENDED
|
||||||
}
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
// TODO: Actually check for cutout
|
val displayCutout = context?.window?.decorView?.rootWindowInsets?.displayCutout
|
||||||
return true
|
if (displayCutout?.safeInsetTop != null || displayCutout?.safeInsetBottom != null)
|
||||||
}
|
return CutoutSupport.MODERN
|
||||||
/*
|
} else if (isVivo) {
|
||||||
else if (isVivo && context != null) {
|
|
||||||
// https://swsdl.vivo.com.cn/appstore/developer/uploadfile/20180328/20180328152252602.pdf
|
// https://swsdl.vivo.com.cn/appstore/developer/uploadfile/20180328/20180328152252602.pdf
|
||||||
try {
|
try {
|
||||||
@SuppressLint("PrivateApi")
|
@SuppressLint("PrivateApi")
|
||||||
val ftFeature = context.classLoader
|
val ftFeature = context?.classLoader
|
||||||
.loadClass("android.util.FtFeature")
|
?.loadClass("android.util.FtFeature")
|
||||||
val isFeatureSupportMethod = ftFeature.getMethod(
|
val isFeatureSupportMethod = ftFeature?.getMethod(
|
||||||
"isFeatureSupport",
|
"isFeatureSupport",
|
||||||
Int::class.javaPrimitiveType
|
Int::class.javaPrimitiveType,
|
||||||
)
|
)
|
||||||
val isNotchOnScreen = 0x00000020
|
val isNotchOnScreen = 0x00000020
|
||||||
return isFeatureSupportMethod.invoke(ftFeature, isNotchOnScreen) as Boolean
|
val isSupported = isFeatureSupportMethod?.invoke(ftFeature, isNotchOnScreen) as Boolean
|
||||||
|
if (isSupported) return CutoutSupport.LEGACY
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
} else if (isMiui) {
|
||||||
|
try {
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
|
val sysProp = context?.classLoader?.loadClass("android.os.SystemProperties")
|
||||||
|
val method = sysProp?.getMethod("getInt", String::class.java, Int::class.javaPrimitiveType)
|
||||||
|
val rt = method?.invoke(sysProp, "ro.miui.notch", 0) as Int
|
||||||
|
if (rt == 1) return CutoutSupport.LEGACY
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
return CutoutSupport.NONE
|
||||||
return false
|
}
|
||||||
|
|
||||||
|
fun getCutoutHeight(context: Activity?, cutoutSupport: CutoutSupport): Number {
|
||||||
|
return when (cutoutSupport) {
|
||||||
|
CutoutSupport.MODERN -> {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
|
||||||
|
throw IllegalStateException("Modern cutout only available on Android P or higher")
|
||||||
|
context?.window?.decorView?.rootWindowInsets?.displayCutout?.safeInsetTop ?: 0
|
||||||
|
}
|
||||||
|
CutoutSupport.EXTENDED -> {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
|
||||||
|
throw IllegalStateException("Extended cutout only available on Android Q or higher")
|
||||||
|
context?.window?.decorView?.rootWindowInsets?.displayCutout?.boundingRectTop?.height()?.toFloat() ?: 0f
|
||||||
|
}
|
||||||
|
CutoutSupport.LEGACY -> {
|
||||||
|
if (isVivo) {
|
||||||
|
val insetCompat = context?.window?.decorView?.rootWindowInsets?.let {
|
||||||
|
WindowInsetsCompat.toWindowInsetsCompat(it)
|
||||||
|
}
|
||||||
|
val statusBarHeight = insetCompat?.getInsets(WindowInsetsCompat.Type.statusBars())?.top
|
||||||
|
?: 24.dpToPx // 24dp is "standard" height for Android since Marshmallow
|
||||||
|
var notchHeight = 32.dpToPx
|
||||||
|
if (notchHeight < statusBarHeight) {
|
||||||
|
notchHeight = statusBarHeight
|
||||||
|
}
|
||||||
|
notchHeight
|
||||||
|
} else if (isMiui) {
|
||||||
|
val resourceId = context?.resources?.getIdentifier("notch_height",
|
||||||
|
"dimen", "android") ?: 0
|
||||||
|
if (resourceId > 0) {
|
||||||
|
context?.resources?.getDimensionPixelSize(resourceId) ?: 0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class CutoutSupport {
|
||||||
|
NONE,
|
||||||
|
LEGACY, // Pre-Android P, the start of this hell
|
||||||
|
MODERN, // Android P
|
||||||
|
EXTENDED, // Android Q
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class LegacyCutoutMode {
|
enum class LegacyCutoutMode {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue