A complete practical guide on how to implement an ActionBar for Android 2.1+ using the Android Support Library.
It also explains how to migrate to ActionBarCompat if you are already familiar with ActionBarSherlock.
Note: this presentation is suitable for AppCompat up to version 20. Instructions have changed a bit in the more recent versions.
2. About the speaker
● Mobile developer living in Brussels.
● Regular attendee of GTUG
and Café Numerique.
● Developed Brussels Transports for Android
during my spare time.
@BladeCoder
plus.google.com/+ChristopheBeyls
3. Agenda
● Introduction to the support library
● ActionBarCompat vs
ActionBarSherlock
● Setup & detailed usage
● Limitations & workarounds
● Migrating from ActionBarSherlock to
ActionBarCompat
● Bugs & fixes
4. The Android Support Library - Features
Mandatory library for (almost) any kind of
Android project.
● Brings Fragments and Loaders to Android
1.6+
● Utility classes to use newer Android
features only if available
○ TaskStackBuilder, NavUtils (navigation)
○ NotificationCompat
○ ShareCompat
5. The Android Support Library - Features
● General utility classes
○
○
○
○
LocalBroadcastManager (message bus)
LruCache (backport)
LongSparseArray (backport)
WakefulBroadcastReceiver
● New UI widgets
○ ViewPager (+ PagerTabStrip, PagerTitleStrip)
○ SlidingPaneLayout
○ DrawerLayout
7. ActionBarCompat vs
ActionBarSherlock
Roughly similar to ActionBarSherlock, but:
● Supported & used by Google
● Makes your code cleaner with less
dependencies
● Produces a slightly smaller apk file
● Fully supports ActionBarDrawerToggle
9. Behaviour
ActionBarCompat works in two different
modes depending on the Android version.
● Android 2.1 to 3.2
A compatibility ActionBar will be used.
It is drawn inside the main content view.
● Android 4+
The native ActionBar will be used.
Method calls will be routed to the native
implementation.
10. Project Setup
Update Android Support Library to the latest version.
● Eclipse
Import library project from local folder:
[sdk]/extras/android/support/v7/appcompat
/android-support-v7-appcompat
● Android Studio
Add dependency to build.gradle:
dependencies {
compile "com.android.support:appcompat-v7:18.0.+"
...
}
11. Usage - Styles
First, make your app styles inherit from
ActionBarCompat styles.
/res/values/styles.xml
<style name="AppTheme" parent="@style/Theme.AppCompat">
...
</style>
● Theme.AppCompat
● Theme.AppCompat.Light
● Theme.AppCompat.Light.DarkActionBar
12. Usage - Styles
To customize the ActionBar appearance,
double-set each attribute in the theme.
<style name="AppTheme" parent="@style/Theme.AppCompat">
<item name="android:actionBarStyle">
@style/myapp_ActionBar</item>
<item name="actionBarStyle">@style/myapp_ActionBar</item>
</style>
<style name="myapp_ActionBar"
parent="@style/Widget.AppCompat.ActionBar">
<item name="android:background">
@drawable/custom_background</item>
<item name="background">@drawable/custom_background</item>
</style>
13. Usage - ActionBarActivity
Make your Activities inherit from
ActionBarActivity and use the support methods.
public class MyActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle("Hello DevFest!");
...
}
}
14. Usage - ActionBarActivity
ActionBar-related support methods
● getSupportActionBar()
● supportInvalidateOptionsMenu()
● supportRequestWindowFeature() [not in ABS]
● setSupportProgress()
● setSupportProgressBarIndeterminateVisibility()
● startSupportActionMode()
Never call the corresponding native methods
if you use ActionBarCompat!
Always call these methods after super.onCreate()
15. Usage - ActionBarActivity
Example - Showing a Progress Bar
public class ProgressActivity extends ActionBarActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.content);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle("Hello DevFest!");
...
}
private void startLoading() {
setSupportProgressBarIndeterminateVisibility(true);
getSupportLoaderManager().initLoader(MY_LOADER_ID, null, myLoaderCallbacks);
}
}
16. Usage - ActionBarActivity
Single Fragment container
Typical code
public class SingleFragmentActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle("Hello DevFest!");
if (savedInstanceState == null) {
MyFragment f = MyFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, f).commit();
}
}
}
➔ Will not work with ActionBarCompat.
17. Usage - ActionBarActivity
Single Fragment container
Universal code
public class SingleFragmentActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle("Hello DevFest!");
if (savedInstanceState == null) {
MyFragment f = MyFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.app_content, f).commit();
}
}
}
18. Usage - ActionBarActivity
Single Fragment container
Universal code
/res/layout/content.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
or just insert the fragment directly in your layout:
<fragment android:name="com.example.myapp.MyFragment"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
20. Usage - Menus
1. Define menus in resources as usual, but use the
app local namespace for Android 3+ attributes.
/res/menu/refresh.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/refresh"
android:icon="@drawable/action_refresh"
android:title="@string/refresh"
app:showAsAction="ifRoom"/>
</menu>
24. Migrating from ActionBarSherlock
to ActionBarCompat
In 7 steps
1. Styles resources
Theme.Sherlock.* ➔ Theme.AppCompat.*
Widget.Sherlock.* ➔ Widget.AppCompat.*
2. SherlockActivity ➔ ActionBarActivity
3. Sherlock*Fragment ➔ *Fragment
4. requestWindowFeature() ➔
supportRequestWindowFeature()
and move the call after super.onCreate()
25. Migrating from ActionBarSherlock
to ActionBarCompat
5. Remove references to the top-level android.
R.id.content and use a custom top
container layout instead.
6. Menu resources
Replace the android: namespace with the
app local namespace for Android 3+ attributes.
7. Menu items code
Replace the ActionBarSherlock MenuItems
with the native MenuItems
+ MenuItemCompat static methods, if needed.
26. Styling Bugs - Issue 58498
1. Too small tabs (on older devices)
27. Styling Bugs
1. Too small tabs - fix
/res/values/styles.xml
<style name="AppTheme" parent="@style/Theme.AppCompat">
...
<item name="android:actionBarTabStyle">
@style/myapp_ActionBarTabStyle</item>
<item name="actionBarTabStyle">@style/myapp_ActionBarTabStyle</item>
</style>
<style name="myapp_ActionBarTabStyle"
parent="@style/Widget.AppCompat.ActionBar.TabView">
...
<!-- AppCompat fix for the compatibility ActionBar -->
<item name="android:minWidth">107dp</item>
</style>
31. One more thing…
Missing feature
No support for preference screens ?
➔ PreferenceActivity is mandatory to support
preference screens on older devices.
➔ There is no ActionBarPreferenceActivity, so:
◆ Either you get no ActionBar at all on the preferences
screen
◆ Or you create two preference activities and use a
native ActionBar on newer devices.
◆ You need to override the styles.
32. Missing feature
Alternative: use a custom PreferenceFragment
● I created a simple PreferenceFragment for
the support library.
● Based on the platform’s
PreferenceFragment with some reflection to
access a few protected methods.
● Works with ActionBarActivity.
● Source code can be found here:
https://gist.github.com/cbeyls
33. The End
Thanks for watching!
@BladeCoder - plus.google.com/+ChristopheBeyls