Tuesday, November 15, 2011

Using MXTabActivityView in MonoCross (MonoDroid flavour)

1. In your application project, add your model - this model will be *shared* by all views within the tabs, plus also shared by the parent tabview itself:
    public class FirstModel
    {
        public List<string> Items1 { get; set; }
        public List<string> Items2 { get; set; }
        public FirstModel()
        {
            Items1 = new List<string>()
                        {
                            "one",
                            "two",
                            "three"
                        };
            Items2 = new List<string>()
                        {
                            "hello",
                            "world",
                            "monocross"
                        };
        }
    }
  
2. Again in your application project, add your controller:
    public class FirstController : MXController<FirstModel>
    {
        public override string Load(Dictionary<string, string> parameters)
        {
            Model = new FirstModel();
            return ViewPerspective.Default;
        }
    }
3. Finally in the application project, make sure you have a route setup for the controller - e.g. a default route like:
            NavigationMap.Add("", new Controllers.FirstController());
4. In your Android container, add the activity views which will sit inside the tabs - e.g.:
    [Activity(Label = "First View!")]
    public class FirstView : MXListActivityView<FirstModel>
    {
        public override void Render()
        {
            ListView.Adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, Model.Items1.OrderBy(x => x).ToList() );
        }
    }
and:
    [Activity(Label = "Second View!")]
    public class SecondView : MXListActivityView<FirstModel>
    {
        public override void Render()
        {
            ListView.Adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, Model.Items2 );
        }
    }
5. In your Android container project, set up your tab activity view - this is a bit like http://docs.xamarin.com/android/tutorials/User_Interface/tab_layout
Set up the xml resource - e.g.:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
  <LinearLayout
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:padding="5dp">
    <TabWidget
        android:id="@android:id/tabs"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp">
    </FrameLayout>
  </LinearLayout>
</TabHost>
Also, add the tab icons if you want them (see notes in http://docs.xamarin.com/android/tutorials/User_Interface/tab_layout)
Then for the MXTabActivityView:
    [Activity(Label = "A TabView!")]
    public class TabView : MXTabActivityView<FirstModel>
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.TabHost);
            TabHost.TabSpec spec;     // Resusable TabSpec for each tab
            Intent intent;            // Reusable Intent for each tab
            // Create an Intent to launch an Activity for the tab (to be reused)
            intent = new Intent(this, typeof(FirstView));
            intent.AddFlags(ActivityFlags.NewTask);
            // Initialize a TabSpec for each tab and add it to the TabHost
            spec = TabHost.NewTabSpec("first");
            spec.SetIndicator("First", Resources.GetDrawable(Resource.Drawable.ic_tab_artists));
            spec.SetContent(intent);
            TabHost.AddTab(spec);
            intent = new Intent(this, typeof(SecondView));
            intent.AddFlags(ActivityFlags.NewTask);
            spec = TabHost.NewTabSpec("second");
            spec.SetIndicator("Second", Resources.GetDrawable(Resource.Drawable.ic_tab_artists));
            spec.SetContent(intent);
            TabHost.AddTab(spec);
       }
        public override void Render()
        {
           // nothing to do here currently!
        }
    }
}
6. That's it! run and enjoy :)

3 comments:

  1. Is there a way to do this where you don't have a *shared* view model?

    Thanks

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. Yes, I do this now in mvvmcross using either a shared view model or using the view model type - and I think the same approach should be available in monocross too - but I'm afraid I don't have any mx samples.

    ReplyDelete