[mono-android] [Monodroid] switching views (again)

Jonathan Pryor jpryor at novell.com
Sat Mar 19 12:08:08 EDT 2011


On Mar 19, 2011, at 9:19 AM, John Murray wrote:
> But I just don’t understand why one cannot do this
>  
> [Activity(Label = "monodlgtest1", MainLauncher = true)]
>     public class Activity1 : Activity
>     {
>         int count = 1;
>         protected override void OnCreate(Bundle bundle)
>         {
>             base.OnCreate(bundle);
>             Button button = FindViewById<Button>(Resource.Id.MyButton);
>             button.Click += delegate { bclick();}
>             Button buttonback = FindViewById<Button>(Resource.Id.goBack);
>             buttonback.Click += delegate { bclick2(); };
>             SetContentView(Resource.Layout.Main);
>         }

Problem #1, which is causing you the most grief at the moment: there is no View until you call SetContentView(). Consequently, you _cannot_ call FindViewById<T>() until _after_ SetContentView() is called. Thus, what you _really_ want is this:

>             base.OnCreate(bundle);
>             SetContentView(Resource.Layout.Main);
>             Button button = FindViewById<Button>(Resource.Id.MyButton);
>             button.Click += delegate { bclick();}
>             Button buttonback = FindViewById<Button>(Resource.Id.goBack);
>             buttonback.Click += delegate { bclick2(); };


That said, you didn't provide the source to bclick() and bclick2(). I assume that each of them uses SetContentView() to set the view. This _should_ work, but remember: when you call SetContentView(), you're loading a _new_ object graph, and thus the buttons are no longer configured for the newly loaded view. Consequently, you need to set them back up again:

	void ConfigureButtons()
	{
		FindViewById<Button>(Resource.Id.MyButton).Click += delegate { bclick(); };
		FindViewById<Button>(Resource.Id.goBack).Click += delegate {bclick2(); };
	}

	protected override void OnCreate (Bundle b)
	{
		base.OnCreate(b);
		SetContentView(Resource.Layout.Main);
		ConfigureButtons();
	}

	void bclick()
	{
		SetContentView (Resource.Layout.ButtonOneClicked);
		ConfigureButtons();
		// ...
	}

	void bclick2()
	{
		SetContentView (Resource.Layout.ButtonTwoClicked);
		ConfigureButtons();
		// ...
	}

Note: I have not tested the above, it just seems plausible.

I would still suggest using Activities over what I outlined above.

> I have read through the fundamentals but being a beginner here it doesn’t always make sense to me
> Can someone explain
> a)      Why the above code doesn’t work

SetContentView() was called too late, as described above.

> b)      How one creates matching activities to each view (I presume that would solve the problem)

I would start with the mindset that an "activity" ISA "view," instead of playing the "let's call SetContentView() multiple times!" game (shown above). Instead, you'd use StartActivity() to navigate to a new view, and when the user clicks the Back button they'll naturally return to the previously running Activity (it's a stack), or call Activity.Finish() (which removes the current Activity from the stack). Thus, there is no need for buttons to take you to the next & previous screens, just the need for a button to take you to the next.

For an example, there's the GoogleMaps sample:

	https://github.com/mono/monodroid-samples/tree/master/GoogleMaps

In which StartActivity() is used to launch a (Java-based in GoogleMaps) activity, but the basic idea is the same: clicking a button launches a new activity, which shows a new screen to the user. When the user clicks the Back button, they'll return to the initial screen:

	https://github.com/mono/monodroid-samples/blob/master/GoogleMaps/Activity1.cs#L26

Another example is the VoiceRecognition API Demo, which launches a new activity to invoke the voice recognizer:

	https://github.com/mono/monodroid-samples/blob/master/ApiDemo/App/VoiceRecognition.cs#L79

> c)       Is there a better way of creating a modal data entry dialog

Once you embrace the mult-activity view, the real concern becomes sharing the model (data) between the various activities. This can be done by stuffing the model into a global (static) variable "somewhere", or using the Application object (similarly global), using Intent.Extras (in theory; I haven't tested to see if there are any limitations here), etc.

 - Jon



More information about the Monodroid mailing list