Search code examples
xamarinxamarin.androidandroid-alertdialogonbackpressed

Xamarin, C#, ALertDialog and OnBackPressed


I have the following code:

using Android.App;
using Android.OS;
using Android.Util;
using Android.Views;

namespace TestIt {
    [Activity( Label = "TestIt", MainLauncher = true, Icon = "@drawable/icon", Theme = "@android:style/Theme.Dialog" )]
    public class TestIt:Activity {

        public static readonly string progName = "TestIt";

        public static AlertDialog builder = null;

        protected override void OnCreate(Bundle bundle) {

            base.OnCreate(bundle);

            Log.Debug(progName, "OnCreate entered");

            builder = (new AlertDialog.Builder( this )).Create();

            Log.Debug(progName, "Build Alert");

            builder.Window.SetType(WindowManagerTypes.SystemAlert);
            builder.SetCancelable(true);
            builder.SetTitle("Test");
            builder.SetMessage("This is a test message");
            builder.Show();

            Log.Debug(progName, "Build Alert Ending"); 

        }

        public override void OnBackPressed() {
            Log.Debug(progName, "OnBackPressed Entered");

            if(builder != null) {
                builder.Cancel();
            }

            base.OnBackPressed();
            Finish();
        }
    }
}

Everything works fine and the alert is displayed.

But OnBackPressed is NOT entered when the Back key is pressed.

Instead I get the message in LogCat:

Attempted to finish an input event but the input event receiver has already been disposed.

I have seen several Java and a couple of Xamarin attempts to solve this but the technique is generally buried quite deep in the function of the sample.

Could someone offer some C# (Xamarin) insight on how to adapt this code such that OnBackPressed (or an alternative) is entered.

I just need to reach to the Back key.

Regards, Jim


Solution

  • This is because, the dialog is consuming the back button press, first. This press cancels the dialog. Another back button press will call your overloaded method.

    I assume you want to close the activity, if the user cancels the dialog. If so, just react on it:

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
    
        // ...
    
        // attach the event listener
        builder.CancelEvent += OnDialogCancel;
        builder.Show();
    }
    
    private void OnDialogCancel(object sender, EventArgs eventArgs)
    {
        builder.CancelEvent -= OnDialogCancel;
        Finish();
    }
    

    If you really need the Back button pressed, while the dialog is shown, you have to inherit your own dialog and override OnBackPressed there.

    public class MainActivity : Activity
    {
        // ...
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
    
            // ...
            builder = new MyAlertDialog(this);
    
            Log.Debug(progName, "Build Alert");
            builder.SetCancelable(true);
            builder.SetTitle("Test");
            builder.SetMessage("This is a test message");
            builder.Show();
    
            Log.Debug(progName, "Build Alert Ending");
        }
    }
    
    public class MyAlertDialog : AlertDialog
    {
        public MyAlertDialog(Context context) : base(context)
        {
        }
    
        public override void OnBackPressed()
        {
            Log.Debug("foo", "OnBackPressed Entered");
            base.OnBackPressed();
        }
    }