2

I want to customise the alert dialog title background and the app crashes without showing the alert dialog. (The custom view only fill the message area excluding the title panel and buttons panel. I want to customise the default title panel and buttons panel. Here I take title as an example.)

public static class MyAlertDialog
{
    private static AlertDialog _alertDialog;

    public static void Show(Context context)
    {
        var factory = LayoutInflater.From(context);
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context)
            .SetTitle("myTitle")
            .SetView(factory.Inflate(Resource.Layout.DialogRegister, null))
            .SetCancelable(true);

        _alertDialog = alertDialogBuilder.Create();
        var titleView = (TextView)_alertDialog.FindViewById(Android.Resource.Id.Title); //get title view from the Android resource not from my custom view
        //titleView.SetBackgroundResource(Resource.Color.PrimaryColor);
        titleView.SetBackgroundColor(Android.Graphics.Color.Red); 
        _alertDialog.Show();  

    }
}

I call the dialog from the main acitivity:

[Activity(Label = "My Activity", MainLauncher = true)]
public class HomeActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        SetContentView(Resource.Layout.home);

        Button btnMyButton = FindViewById<Button>(Resource.Id.MyButton);
        btnMyButton.Click += (object sender, EventArgs e) =>
        {
            MyAlertDialog.Show(this);
        };

        ......
     }
 }

The VS throws an runtime exception and ask me to break or continue. I click on continue. Then app crashes. The log:

03-09 11:10:47.057 E/mono    ( 1185): [0x4001f730:] EXCEPTION handling: Android.Util.AndroidRuntimeException: Exception of type 'Android.Util.AndroidRuntimeException' was thrown.
03-09 11:10:49.956 I/Email   (  451): ReconcilePopImapAccountsSync: start
03-09 11:10:50.276 I/Email   (  451): ReconcilePopImapAccountsSync: done
03-09 11:11:07.417 E/mono    ( 1185): [0x4001f730:] EXCEPTION handling: Java.Lang.NullPointerException: Exception of type 'Java.Lang.NullPointerException' was thrown.
03-09 11:11:07.727 E/mono    ( 1185): [0x4001f730:] EXCEPTION handling: Java.Lang.NullPointerException: Exception of type 'Java.Lang.NullPointerException' was thrown.
03-09 11:11:16.846 F/        ( 1185): * Assertion: should not be reached at /Users/builder/data/lanes/monodroid-lion-bigsplash/0e0e51f9/source/mono/mono/mini/debugger-agent.c:5980
03-09 11:11:16.846 I/mono    ( 1185): Stacktrace:
03-09 11:11:16.846 I/mono    ( 1185): 
03-09 11:11:16.866 E/mono    ( 1185): [0x2a118c70:] EXCEPTION handling: System.NullReferenceException: Object reference not set to an instance of an object
03-09 11:11:16.906 E/mono    ( 1185): 
03-09 11:11:16.906 E/mono    ( 1185): Unhandled Exception:
03-09 11:11:16.906 E/mono    ( 1185): System.NullReferenceException: Object reference not set to an instance of an object
03-09 11:11:16.937 I/mono    ( 1185): [ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object

I test it in the emulator with Android 4.1.2 armeabi-v7a. (The project is set to support architectures armeabi, armeabi-v7a and x86.)

Thanks for any help. (I know I could put the title with message in a custom content view. But I also want to customise other part of it. So I just take the title as an example.)

I notice although I SetTitle("myTitle"), the titleView.text is an empty string. Was I wrong in getting the default title view by

var titleView = (TextView)_alertDialog.FindViewById(Android.Resource.Id.Title);

Again, my custom view does not contain the title view.

user769923
  • 247
  • 1
  • 5
  • 15

3 Answers3

3

Your code is messy, there may be multiple issues but I think this line is your problem

txView.SetBackgroundResource(Resource.Color.PrimaryColor);

As you can see here in the documentation you should only pass a reference to a Drawable as the parameter not a Color.

You need to use this method here like so: txView.SetBackgroundColor(Resource.Color.PrimaryColor);

Also the code in the question won't compile, where does the txView variable come from? I'm assuming it's meant to be titleView?

And another thing; the log entry you have posted will be displayed every time you run your project, you can ignore it. See here for more info. The actual log entry you should have posted would have come much later (and only after you click Continue in Visual Studio)

Alex Wiese
  • 8,142
  • 6
  • 42
  • 71
  • sorry for the typo here. The txView should be 'titleView'. And I have tried SetBackgroundColor with no luck (before I posted the question here). – user769923 Mar 09 '13 at 10:50
  • The custom view only fill the message area excluding the title panel. I want to get the default title view and customise it. – user769923 Mar 09 '13 at 10:56
  • OK now I understand what you are trying to do. Did you definitely check that `titleView != null`? Because what you are trying to do isn't possible. To style an AlertDialog you need to use a custom style like [this](http://stackoverflow.com/a/3870997/1411687) – Alex Wiese Mar 09 '13 at 11:20
  • @user769923 Yes there is a null reference exception in the log. I'm pretty sure titleView is null. Please check your variables again and find which one is null. – Alex Wiese Mar 09 '13 at 11:21
  • I now checked that titleView != null. And I read [that](http://stackoverflow.com/questions/2422562/how-to-change-theme-for-alertdialog/3870997#3870997). I tried to avoid using ContextThemeWrapper because for API 10 and below, the alertdialog uses Theme.Dialog.Alert and for newer API, it uses Theme.Holo.Dialog.Alert. My app will support API8+. So I do not know what parent style should I use for the custom alertDialog style. – user769923 Mar 09 '13 at 11:46
  • Maybe you can create two styles, each implementing a different parent style and determine API level at runtime using `Android.OS.Build.VERSION.SdkInt` to choose which one to use – Alex Wiese Mar 09 '13 at 11:51
1

You need to tell which view to find id in. So instantiate a view after get the factory.

var view = factory.Inflate(Resource.Layout.DialogRegister, null);

Because the titleView would reference to null, it causes the crash,

Then, you can find the title using the view you just created. One thing to point out, Android.Resource references to resources of Android framework in Mono for Android, and Resource is actually the reference to your layouts, ids etc. So, the code would be like:

var titleView = view.FindViewById<TextView>(Resource.Id.title);

SetBackgroundResource can only take drawable as an effective parameter, so color won't work in this case. However SetBackgroundColor would work because Android.Graphics.Color.Red is a Color object.

Also, you can SetView(view) while building the dialog.

Aaron He
  • 5,509
  • 3
  • 34
  • 44
  • In my code, the titleView is found from _alertDialog so it is not null. And the Resource.Color.PrimaryColor is a reference to a color resource. – user769923 Mar 09 '13 at 08:21
  • If you want to have a custom title, consider using `AlertDialog.SetCutomTitle` or `AlertDialog.SetIcon`. http://androidapi.xamarin.com/?link=T%3aAndroid.App.AlertDialog%2bBuilder%2fM. Or just include the title into your custom view. I tested your code, but if using alertdialog to find the `Android.Resource.Id.title` it returns null and causes crash. – Aaron He Mar 09 '13 at 20:31
  • Thanks Aaron. Android.Resource.Id.title seems not the title view of the dialog. I tried putting the title in a custom view and got the [issue](http://stackoverflow.com/q/15305791/769923). – user769923 Mar 10 '13 at 18:26
0

I would just use dialogs. You override the OnCreateDialog method. There you can set a contentview and set a custom title if needed. You can also customize the dialog.Here is some example code, there is a SetTitle method. Here is a brief example more can be found at the link below the code.

This code shows how to wire up a button click to show the dialog. Once the button is clicked the OnCreateDialog will be called and the system will show your dialog.

const int NewGame = 1;
protected override Dialog OnCreateDialog(int id)
    {
        switch (id)
        {
            case NewGame:
                Dialog d = new Dialog(this);// Create the new dialog
                d.SetTitle("New Game");//Set the title.
                d.SetContentView(Resource.Layout.ActNewGame);//Set the layout resource.
                //here you can use d.FindViewById<T>(Resource)
             return d;
        }
        return null;
    }

}

// wire up a button click in the OnCreate method.
btnNewGame.Click += (o, e) =>
        {

                ShowDialog(NewGame);
        };

http://xandroid4net.blogspot.com/2014/09/xamarinandroid-ways-to-customize-dialogs.html