'Get activity context inorder to open alert dialog from non-composable function using compose context
I have another API library which things happens inside, and I would like to show a dialog if some case happen and options what to do on them if accept / decline, When the dialog need to shows it crashed, BTW is theres any way to get activity context from compose inorder to allow it shows alert dialog in any other compose function I use with my only single activity app? I've tried AlertDialog.Builder(context) as well and same results,
My minimal example:
@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()
}
}
update: error stack:
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$1.invoke(MainActivity.kt:43)
at com.rayan.alertdialogproblem.MainActivityKt$Check$1.invoke(MainActivity.kt:42)
at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke-k-4lQ0M(Clickable.kt:137)
at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke(Clickable.kt:137)
at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1$1.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)
Solution 1:[1]
The error says that the dialog requires a theme. You can provide it with ContextThemeWrapper, either a custom one declared in res/values/themes, or a default one, like R.style.Theme_MaterialComponents_Dialog:
MaterialAlertDialogBuilder(ContextThemeWrapper(context, R.style.Theme_MaterialComponents_Dialog))
More info about custom theming can be found here
Solution 2:[2]
You should use the composable 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")
}
}
The properties available :
- title : Composable that will be shown at the top of the dialog
- text : Composable that will be shown at the center of the dialog
- buttons : Composable that will be shown at the bottom of the dialog
If you want to know every properties check the link above or use android studio to check the properties.
Solution 3:[3]
This is an error in theme... You need to set the theme of the MainActivity.kt in your AndroidManifest.xml file. And, that theme (in the styles.xml) has to have a parent called "Theme.AppCompat"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Pylyp Dukhov |
| Solution 2 | |
| Solution 3 | laggyPC |
