获取 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”的父级“
”
我有另一个 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”的父级“
”