4

I am trying to reuse the NavigationBar from the Android ActionBar to navigate between screens. Since each screen contains lots of separate logic, I would like to have an Activity for each screen, but each screen should reuse the ActionBar since it contains the navigation and other custom views.

In order to do this I created a base activity class that generates the appropriate action bar. The following code works as I expect but something doesn't feel quite right. It just seems like I am doing too much working for something that should be simpler. Also, even though my base activity reuses a lot of code, it doesn't actually reuse the ActionBar in memory.

Is there a different native navigation control that I could use to achieve this? I do not want to do custom layout inflating or create a custom navigation bar.

Also, I am using Xamarin's Mono for Android.

Base Navigation Activity

public abstract class BaseNavigationActivity : Activity
{
    private NavigationScreens[] _availableScreens = { NavigationScreens.Screen1, NavigationScreens.Screen2 };
    private NavigationScreens _currentScreen = NavigationScreens.Unknown;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Remove ActionBar icon and title. Also allow custom view.
        ActionBar.SetDisplayShowHomeEnabled(false);
        ActionBar.SetDisplayShowTitleEnabled(false);

        // Navigation bar
        ScreenNavigationAdapter screenAdapter = new ScreenNavigationAdapter(this, _availableScreens);
        ScreenNavigationListener navigationListener = new ScreenNavigationListener(this, screenAdapter);

        ActionBar.NavigationMode = ActionBarNavigationMode.List;
        ActionBar.SetListNavigationCallbacks(screenAdapter, navigationListener);
    }

    protected override void OnResume()
    {
        base.OnResume();

        // Set the navigation item on the action bar to be the current screen
        ActionBar.SetSelectedNavigationItem(Array.FindIndex(_availableScreens, x => x == _currentScreen));
    }

    public NavigationScreens CurrentScreen
    {
        get { return _currentScreen; }
    }

    public BaseNavigationActivity(NavigationScreens screen)
    {
        _currentScreen = screen;
    }

Sample Activity

[Activity(Label = "ActionBarTest", MainLauncher = true, Theme = "@style/CustomActionBarStyle", LaunchMode = LaunchMode.SingleInstance)]
public class ActionBarNavigationTestActivity : BaseNavigationActivity
{
    public ActionBarNavigationTestActivity()
        : base(NavigationScreens.Screen1)
    {
    }

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.ActionBarNavigation);
    }
}

Adapters and Listeners

public class ScreenNavigationAdapter : BaseAdapter
{
    private IEnumerable<NavigationScreens> _screens;
    private LayoutInflater _layoutInflater;

    public ScreenNavigationAdapter(Context context, IEnumerable<NavigationScreens> screens)
    {
        _screens = screens;

        // Retrieve the layout inflater from the provided context
        _layoutInflater = LayoutInflater.FromContext(context);
    }

    public override Java.Lang.Object GetItem(int position)
    {
        return null;
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        var view = convertView;

        // Try to reuse views as much as possible.
        if (view == null)
        {
            // inflate a new layout for the view.
            view = _layoutInflater.Inflate(Resource.Layout.SpinnerViewLayout, parent, false);
        }

        TextView textView = view.FindViewById<TextView>(Resource.Id.MenuText);
        textView.Text = _screens.ElementAt(position).ToString();

        return view;
    }

    public override int Count
    {
        get { return _screens.Count(); }
    }

    public NavigationScreens GetScreenAt(int position)
    {
        return _screens.ElementAt(position);
    }
}

public class ScreenNavigationListener : Java.Lang.Object, ActionBar.IOnNavigationListener
{
    private readonly BaseNavigationActivity _currentActivity = null;
    private readonly ScreenNavigationAdapter _adapter = null;

    public ScreenNavigationListener(BaseNavigationActivity currentScreen, ScreenNavigationAdapter adapter)
    {
        _currentActivity = currentScreen;
        _adapter = adapter;
    }

    public bool OnNavigationItemSelected(int itemPosition, long itemId)
    {
        NavigationScreens selectedScreen = _adapter.GetScreenAt(itemPosition);
        if (_currentActivity.CurrentScreen == selectedScreen)
        {
            // Already displaying the selected screen, dont do anything
            return true;
        }

        Intent intent = null;
        if (selectedScreen == NavigationScreens.Screen1)
        {
            intent = new Intent(_currentActivity, typeof(ActionBarNavigationTestActivity));
        }

        if (selectedScreen == NavigationScreens.Screen2)
        {
            intent = new Intent(_currentActivity, typeof(ActionBarNavigationTestActivity2));
        }

        if (intent != null)
        {
            intent.SetFlags(ActivityFlags.NoAnimation);
            _currentActivity.StartActivity(intent);

            return true;
        }

        return false;
    }
}

public enum NavigationScreens
{
    Unknown = -1,
    Screen1 = 0,
    Screen2
}
Alex
  • 2,033
  • 1
  • 24
  • 40
  • 5
    You should really switch to using Fragments, not Activities, this will save you lots of time and effort. – Egor May 29 '13 at 19:32
  • 1
    I would follow Egor's advice, the other option if you were to not use `Fragments` would be to basically recreate the navigation bar for each `Activity` you make. – Bryan May 29 '13 at 20:09
  • 1
    Wow, absolutely correct. I should have read more about Fragments. They have their own life-cycle separate, get to reuse action bar, and code is separated. Prototype works perfectly. Can one of you post an answer so that I can accept. Thanks. – Alex May 29 '13 at 21:38

0 Answers0