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

Time:02-25

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)

thanks in advance

CodePudding user response:

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

CodePudding user response:

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.

CodePudding user response:

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"

  • Related