获取 activity 上下文以便使用组合上下文从不可组合函数打开警报对话框

Get activity context inorder to open alert dialog from non-composable function using compose context

我有另一个 API 库,里面发生了一些事情,我想在某些情况发生时显示一个对话框,并选择如果接受/拒绝如何处理它们, 当对话框需要显示它崩溃时, 顺便说一句,有什么方法可以从 compose 中获取 activity 上下文,以便允许它在我与我唯一的单个 activity 应用程序一起使用的任何其他 compose 函数中显示警报对话框? 我也尝试了 AlertDialog.Builder(context) 并且结果相同,

我的最小示例:

@Composable
fun Check(){
    val context = LocalContext.current
    Button(onClick= {
        TestObject.alert(context)
    }){
        Text("Test")
    }
}

object TestObject{

... //things happend there
    fun alert(context: Context){
        ... //things happend there
        MaterialAlertDialogBuilder(context)
            .setTitle("Hi")
            .setMessage("Hello World")
            .setNeutralButton("OK", null)
            .show()
    }
}

更新:错误堆栈:

dRuntime: FATAL EXCEPTION: main
    Process: com.rayan.alertdialogproblem, PID: 4980
    java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
        at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:241)
        at com.google.android.material.internal.ThemeEnforcement.checkAppCompatTheme(ThemeEnforcement.java:211)
        at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:146)
        at com.google.android.material.internal.ThemeEnforcement.obtainStyledAttributes(ThemeEnforcement.java:75)
        at com.google.android.material.dialog.MaterialDialogs.getDialogBackgroundInsets(MaterialDialogs.java:60)
        at com.google.android.material.dialog.MaterialAlertDialogBuilder.<init>(MaterialAlertDialogBuilder.java:117)
        at com.google.android.material.dialog.MaterialAlertDialogBuilder.<init>(MaterialAlertDialogBuilder.java:103)
        at com.rayan.alertdialogproblem.TestObject.alert(MainActivity.kt:58)
        at com.rayan.alertdialogproblem.MainActivityKt$Check.invoke(MainActivity.kt:43)
        at com.rayan.alertdialogproblem.MainActivityKt$Check.invoke(MainActivity.kt:42)
        at androidx.compose.foundation.ClickableKt$clickable$gesture.invoke-k-4lQ0M(Clickable.kt:137)
        at androidx.compose.foundation.ClickableKt$clickable$gesture.invoke(Clickable.kt:137)
        at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress.invokeSuspend(TapGestureDetector.kt:378)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:178)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:398)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:432)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:421)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:329)
        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:432)
        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.dispatchPointerEvent(SuspendingPointerInputFilter.kt:330)
        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:343)
        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:287)
        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:275)
        at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:151)
        at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:90)
        at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-gBdvCQM(PointerInputEventProcessor.kt:77)
        at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:860)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:502)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1890)
        at android.app.Activity.dispatchTouchEvent(Activity.java:4196)
E/AndroidRuntime:     at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:460)
        at android.view.View.dispatchPointerEvent(View.java:14799)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6347)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6148)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5626)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5683)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5649)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5814)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5657)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5871)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5683)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5649)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5657)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8562)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8513)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8482)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8685)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:259)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:335)
        at android.os.Looper.loopOnce(Looper.java:161)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7839)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

您应该使用可组合的 AlertDialog https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#alertdialog

@Composable
fun Check(){
    val showDialog by remember { mutableStateOf(false) }
    
    if(showDialog) {
        AlertDialog(
             onDismissRequest = {
                    showDialog = false
             },
        )
    }

    Button(onClick= {
        showDialog = true
    }){
        Text("Test")
    }
}

可用的属性:

  • 标题:将显示在对话框顶部的可组合项
  • 文本:将显示在对话框中心的可组合项
  • 按钮:将显示在对话框底部的可组合项

如果您想了解每个属性,请查看上面的 link 或使用 android studio 查看属性。

错误提示对话框需要主题。您可以为它提供 ContextThemeWrapper,可以是在 res/values/themes 中声明的自定义的,也可以是默认的,例如 R.style.Theme_MaterialComponents_Dialog:

MaterialAlertDialogBuilder(ContextThemeWrapper(context, R.style.Theme_MaterialComponents_Dialog))

可以找到有关自定义主题的更多信息here

这是主题错误...您需要在 AndroidManifest.xml 文件中设置 MainActivity.kt 的主题。而且,该主题(在 styles.xml 中)必须有一个名为“Theme.AppCompat”的父级“