ActionBarCompat – Part 4

In the previous article we began converting our code to work with ActionBarCompat, but there are still some further changes required to get things working. In this article we’ll complete the code migration.

The next thing that we must do is change our ActionMode handling because ActionMode is unsurprisingly tied in to ActionBarCompat. Starting an ActionMode is simply a case of changing the method call to it’s support variant. So onOptionsItemSelected() changes from:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

@Override

public boolean onOptionsItemSelected( MenuItem item )

{

boolean ret;

if (item.getItemId() == R.id.menu_settings)

{

// Handle Settings

ret = true;

} else if (item.getItemId() == R.id.menu_toggle)

{

ActionBar ab = getActionBar();

if (ab.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS)

{

setListNavigation( ab );

mSearchItem.setVisible( false );

} else

{

setTabNavigation( ab );

mSearchItem.setVisible( true );

}

ret = true;

} else if( item.getItemId() == R.id.menu_actionmode)

{

startActionMode( mCallback );

ret = true;

} else

{

ret = super.onOptionsItemSelected( item );

}

return ret;

}

to:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

@Override

public boolean onOptionsItemSelected( MenuItem item )

{

boolean ret;

if (item.getItemId() == R.id.menu_settings)

{

// Handle Settings

ret = true;

} else if (item.getItemId() == R.id.menu_toggle)

{

ActionBar ab = getActionBar();

if (ab.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS)

{

setListNavigation( ab );

mSearchItem.setVisible( false );

} else

{

setTabNavigation( ab );

mSearchItem.setVisible( true );

}

ret = true;

} else if( item.getItemId() == R.id.menu_actionmode)

{

startSupportActionMode(mCallback);

ret = true;

} else

{

ret = super.onOptionsItemSelected( item );

}

return ret;

}

The next thing that we must do is change our ActionView implementation. The existing code for this is:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

private ActionMode.Callback mCallback = new ActionMode.Callback()

{

.

.

.

@Override

public boolean onCreateActionMode( ActionMode mode, Menu menu )

{

MenuInflater inflater = mode.getMenuInflater();

inflater.inflate( R.menu.actionmode, menu );

MenuItem item = menu.findItem( R.id.action_text );

View v = item.getActionView();

if( v instanceof TextView )

{

((TextView)v).setText( R.string.actionmode_title );

}

return true;

}

.

.

.

}

While the import change has already converted most of this, the highlighted line does not work because the getActionView() method was added in API 11 so is unavailable to us. We can get around this thanks to a utility class from the compat library named MenuItemCompat which provides implementations of some of the ActionProvider / ActionView related methods which were added in API 11. In our case, we need the getActionView() method, and this is implemented as a static method which takes a single, MenuItem argument:

Java

1

Viewv=MenuItemCompat.getActionView(item);

The final thing that we need to do is change the layout resources that we use for our Spinner Adapters:

Java

1

2

3

SimpleAdapter adapter=newSimpleAdapter(this,data,

android.R.layout.simple_spinner_dropdown_item,

newString[]{"title"},newint[]{android.R.id.text1});

Instead of android.R.layout.simple_spinner_dropdown_item we should use a layout provided by the library:

Java

1

2

3

4

SimpleAdapter adapter=newSimpleAdapter(

getSupportActionBar().getThemedContext(),data,

R.layout.support_simple_spinner_dropdown_item,

newString[]{"title"},newint[]{android.R.id.text1});

There is also a bug in the original code that we’re fixing here. We should be specifying a themed Context in the first argument of the SpinnerAdapter constructor, and we can obtain this from the support ActionBar implementation (Thanks to Chris Banes for pointing this out).

Our code migration to ActionBarCompat, and our project will now compile and run on devices back to API 7. However, things are not completely seamless and in the concluding article in this series we’ll compare things on different devices, and cover some of the differences that you should be aware of when using ActionBarCompat.