Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: NavigationDrawer and ActionBarCompat

I started working with NavigationDrawer using ActionBarSherlock and got good results, but my company approving this Open Source is not likely to come anytime soon, so I'm working to switch to ActionBarCompat.

ActionBarCompat was just officially released yesterday (July 24th, 2013). Has anyone gotten both to work well with each other? I'm hoping I can answer my own question, but seeing if anyone has gotten this to work. The race is on! :-)

YouTube on ActionBarCompat's release: https://www.youtube.com/watch?v=6TGgYqfJnyc


UPDATE (working code, yes!): I've gotten the sample NavigationDrawer app from Google converted to use ActionBarCompat and it is working fine. You can find it here as a reference or start to your project: https://github.com/bcrider/NavigationDrawerActionBarCompat

The 2.x version looks even better than the way it did with ActionBarSherlock, but I'll have to work with ActionBarCompat a lot more to see if I like it better.


like image 933
Brian Crider Avatar asked Jul 25 '13 19:07

Brian Crider


People also ask

How do we add the component 1 to the navigation drawer?

The drawer icon is displayed on all top-level destinations that use a DrawerLayout . To add a navigation drawer, first declare a DrawerLayout as the root view. Inside the DrawerLayout , add a layout for the main UI content and another view that contains the contents of the navigation drawer.

What is ActionBar in Android?

Android ActionBar is a menu bar that runs across the top of the activity screen in android. Android ActionBar can contain menu items which become visible when the user clicks the “menu” button. In general an ActionBar consists of the following four components: App Icon: App branding logo or icon will be displayed here.


2 Answers

NOTE: I'm too new to add more than one link in a post, etc., so am answering my own question instead of editing it (hope that's not against the rules?). Will edit the original once allowed.

Simple way to add Navigation Drawer with ActionBarCompat: I found that converting my existing app wasn't as bad as I thought it was going to be. Google's sample led me to believe Fragments were a necessity but that wasn't the case... far from it.

You can simply wrap your existing layouts with the DrawerLayout and plug in the ListView (or any layout containing the ListView for that matter) for the actual navigation. Then add the normal code to your existing Activity (extend ActionBarActivity) and build the navigation as you would have to anyway.

Here's some sample code with which to wrap your existing layout:

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

[YOUR EXISTING LAYOUT GOES HERE]

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#111"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />

</android.support.v4.widget.DrawerLayout>

If you want to start with a sample app that does use fragments and go from there, here's my github repository based on the sample code: https://github.com/bcrider/NavigationDrawerActionBarCompat

like image 142
Brian Crider Avatar answered Sep 27 '22 17:09

Brian Crider


I converted my app from ActionBarSherlock to ActionBarCompat yesterday. I've had some problems, but nothing too serious.

I have some comments:

To update the themes, I just needed to override "Sherlock" to "AppCompat". For example, instead of inheriting from @style/Theme.Sherlock.Light.DarkActionBar, I'm inheriting from @style/Theme.AppCompat.Light.DarkActionBar.

For the action items, just update this way:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          yourapp:showAsAction="ifRoom"  />
    ...
</menu>

And in the onCreateOptionsMenu, use the normal MenuItem, but use static methods of MenuItemCompat to do ActionBar's stuff. For example: MenuItemCompat.expandActionView(searchMenuItem);

If you use RoboGuice inheriting from RoboSherlockActivity, you'll have trouble if you just copy it and change to ActionBarActivity. Here's my solution:

public class RoboActionBarActivity extends ActionBarActivity implements RoboContext {

    protected EventManager eventManager;
    protected HashMap<Key<?>, Object> scopedObjects = new HashMap<Key<?>, Object>();

    @Inject
    ContentViewListener ignored; // BUG find a better place to put this

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        final RoboInjector injector = RoboGuice.getInjector(this);
        eventManager = injector.getInstance(EventManager.class);
        injector.injectMembersWithoutViews(this);
        super.onCreate(savedInstanceState);
        eventManager.fire(new OnCreateEvent(savedInstanceState));
    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        contentViewChanged();
    }

    @Override
    public void setContentView(View view) {
        super.setContentView(view);
        contentViewChanged();
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        super.setContentView(view, params);
        contentViewChanged();
    }

    @Override
    public void addContentView(View view, ViewGroup.LayoutParams params) {
        super.addContentView(view, params);
        contentViewChanged();
    }

    private void contentViewChanged() {
        RoboGuice.getInjector(this).injectViewMembers(this);
        eventManager.fire(new OnContentChangedEvent());
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        eventManager.fire(new OnRestartEvent());
    }

    @Override
    protected void onStart() {
        super.onStart();
        eventManager.fire(new OnStartEvent());
    }

    @Override
    protected void onResume() {
        super.onResume();
        eventManager.fire(new OnResumeEvent());
    }

    @Override
    protected void onPause() {
        super.onPause();
        eventManager.fire(new OnPauseEvent());
    }

    @Override
    protected void onNewIntent( Intent intent ) {
        super.onNewIntent(intent);
        eventManager.fire(new OnNewIntentEvent());
    }

    @Override
    protected void onStop() {
        try {
            eventManager.fire(new OnStopEvent());
        } finally {
            super.onStop();
        }
    }

    @Override
    protected void onDestroy() {
        try {
            eventManager.fire(new OnDestroyEvent());
        } finally {
            try {
                RoboGuice.destroyInjector(this);
            } finally {
                super.onDestroy();
            }
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        final Configuration currentConfig = getResources().getConfiguration();
        super.onConfigurationChanged(newConfig);
        eventManager.fire(new OnConfigurationChangedEvent(currentConfig, newConfig));
    }

    @Override
    public void onContentChanged() {
        super.onContentChanged();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        eventManager.fire(new OnActivityResultEvent(requestCode, resultCode, data));
    }

    @Override
    public Map<Key<?>, Object> getScopedObjectMap() {
        return scopedObjects;
    }

}

Now, you start ActionMode with supportStartActionMode() and imports the ActionMode from the library's package.

To use the SearchView, you need to do something like this:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:icon="@drawable/abc_ic_search"
        app:showAsAction="always|collapseActionView"
        android:title="@string/search"/>

</menu>

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_menu, menu);

    searchMenuItem = menu.findItem(R.id.search);
    searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);

    if (searchView != null) {
        searchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            public boolean onQueryTextChange(String newText) {
                return true;
            }

            public boolean onQueryTextSubmit(String query) {
                doSomething(query);
                return true;
            }
        };

        searchView.setOnQueryTextListener(queryTextListener);

    }

    return super.onCreateOptionsMenu(menu);
}

The other things are working with no modification but the package of the imports.

You can see more information here: http://developer.android.com/guide/topics/ui/actionbar.html.

like image 34
Fernando Camargo Avatar answered Sep 27 '22 18:09

Fernando Camargo