Pergunta

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.


Foi útil?

Solução

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

Outras dicas

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.

The samples that come with the 4.3 sdk look promising, but I'm going to create a test project and try to convert my own application to ActionBarCompact and see if it functions better or worse than ActionBarSherlock! I'll update this post if I'm successful or not!

While the provided example is good, I made another example which is a bit closer to the original Google Navigation Drawer example as it includes all original code (now aiming to support library) and formatting. Only some attributes had to be replaced with similar ones as they are only available from v11 onwards.

Download at: https://github.com/GunnarBs/NavigationDrawerWithActionBarCompat

Note: This requires the v7 appcompat library to be present, see http://developer.android.com/tools/support-library/setup.html for details.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top