是否有一个Jetpack Compose等效于android:keepScreenOn来保持屏幕活跃?

hpxqektj  于 2023-04-10  发布在  Android
关注(0)|答案(7)|浏览(176)

我有一个Composable,它使用一个Handler来缓慢地更新Composable内部图像的alpha。然而,我看到屏幕在动画完成之前关闭。
在XML布局中,我们可以使用
android:keepScreenOn

window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
有没有一种不使用唤醒锁权限而使用合成的方法来做到这一点?

w9apscun

w9apscun1#

您可以使用LocalContext来获取活动,它有一个窗口,您可以在其中应用所需的标志。
在这种情况下,当你需要在视图的出现和消失上运行一些代码时,可以使用DisposableEffect

@Composable
fun KeepScreenOn() {
    val context = LocalContext.current
    DisposableEffect(Unit) {
        val window = context.findActivity()?.window
        window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        onDispose {
            window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }
}

fun Context.findActivity(): Activity? {
    var context = this
    while (context is ContextWrapper) {
        if (context is Activity) return context
        context = context.baseContext
    }
    return null
}

用法:当屏幕出现时,标志设置为开,当屏幕消失时,标志被清除。

@Composable
fun Screen() {
    KeepScreenOn()
}

正如@Louis CAD正确指出的,如果在许多视图中使用此“视图”,可能会出现问题:如果出现一个使用它的视图,然后消失先前也使用它的视图,它将重置该标志。
我还没有找到一种跟踪flags状态来更新视图的方法,我认为@Louis CAD solution可以,直到Compose有一些系统支持。

ldioqlga

ldioqlga2#

如果你在同一个组合中有多个用法,这个应该是安全的,不会受到任何干扰:

@Composable
fun KeepScreenOn() = AndroidView({ View(it).apply { keepScreenOn = true } })

用法就这么简单:

if (screenShallBeKeptOn) {
    KeepScreenOn()
}
js5cn81o

js5cn81o3#

以一种更复杂的方式:

@Composable
fun KeepScreenOn() {
    val currentView = LocalView.current
    DisposableEffect(Unit) {
        currentView.keepScreenOn = true
        onDispose {
            currentView.keepScreenOn = false
        }
    }
}

当视图从组合中消失时,它将被处理掉。用法很简单:

@Composable
fun Screen() {
    KeepScreenOn()
}
eagi6jfj

eagi6jfj4#

这就是我如何实现我的
在Composable函数中,我有一个按钮用于激活FLAG_KEEP_SCREEN_ON或清除FLAG_KEEP_SCREEN_ON

@Composable
fun MyButton() {
    var state by rememberSaveable {
        mutableStateOf(false)
    }

    val context = LocalContext.current

    Button(
       ...
       modifier = Modifier
            .clickable {
                state = !state
                keepScreen(state, context)
            }
       ...
     )
}

fun keepScreen(state: Boolean, context : Context) {
   val activity = context as Activity
   if(state) {
     activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
   }else {
   activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
   }
}
xqk2d5yq

xqk2d5yq5#

下面的代码最适合我。

@Composable
fun ScreenOnKeeper() {
    val activity = LocalContext.current as Activity

    DisposableEffect(Unit) {
        activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        onDispose {
            activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }
}

下面的代码在我切换它的存在(有条件地添加、删除、添加组件)时不起作用。

@Composable
fun ScreenOnKeeper() {
    val view = LocalView.current

    DisposableEffect(Unit) {
        view.keepScreenOn = true
        onDispose {
            view.keepScreenOn = false
        }
    }
}
gv8xihay

gv8xihay6#

把它放在你的活动主题中:

<item name="android:keepScreenOn">true</item>

愚蠢,但它工作。

yv5phkfx

yv5phkfx7#

我使用了这个解决方案:

@Composable
fun KeepScreenOn() {
val context = LocalContext.current
AndroidView(
       factory = {
           LinearLayout(context).apply {
               keepScreenOn = true
           }
       },
       modifier = Modifier.wrapContentSize()
   ) {}
}

在所有你想阻止睡眠的可组合的乐趣中,把这个叫做乐趣

相关问题