Android Support Library: Using ActionBarCompat

33
Android Support Library: Using ActionBarCompat Christophe Beyls DevFest Belgium 2013

description

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.

Transcript of Android Support Library: Using ActionBarCompat

Page 1: Android Support Library: Using ActionBarCompat

Android Support Library:Using ActionBarCompat

Christophe Beyls

DevFest Belgium 2013

Page 2: Android Support Library: Using ActionBarCompat

About the speaker

● Mobile developer living in Brussels.● Regular attendee of GTUG

and Café Numerique.● Developed Brussels Transports for Android

during my spare time.

@BladeCoderplus.google.com/+ChristopheBeyls

Page 3: Android Support Library: Using ActionBarCompat

Agenda

● Introduction to the support library● ActionBarCompat vs

ActionBarSherlock● Setup & detailed usage● Limitations & workarounds● Migrating from ActionBarSherlock to

ActionBarCompat● Bugs & fixes

Page 4: Android Support Library: Using ActionBarCompat

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

Page 5: Android Support Library: Using ActionBarCompat

The Android Support Library - Features

● General utility classes○ LocalBroadcastManager (message bus)○ LruCache (backport)○ LongSparseArray (backport)○ WakefulBroadcastReceiver

● New UI widgets○ ViewPager (+ PagerTabStrip, PagerTitleStrip)○ SlidingPaneLayout○ DrawerLayout

Page 6: Android Support Library: Using ActionBarCompat

ActionBarCompat

http://developer.android.com/guide/topics/ui/actionbar.html

● Introduced in may 2013 as part of the Android support library v18

● Requires & extends android-support-v4.jar● Provides ActionBar support for Android 2.1+

(API 7+)● Mimics the native ActionBar API

Page 7: Android Support Library: Using ActionBarCompat

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

Page 8: Android Support Library: Using ActionBarCompat

ActionBarCompat vs ActionBarSherlock

● Android 4+ styled overflow menu

Page 9: Android Support Library: Using ActionBarCompat

Behaviour

ActionBarCompat works in two different modes depending on the Android version.

● Android 2.1 to 3.2A 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.

Page 10: Android Support Library: Using ActionBarCompat

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 StudioAdd dependency to build.gradle:dependencies { compile "com.android.support:appcompat-v7:18.0.+" ...}

Page 11: Android Support Library: Using ActionBarCompat

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

Page 12: Android Support Library: Using ActionBarCompat

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>

Page 13: Android Support Library: Using ActionBarCompat

Usage - ActionBarActivity

Make your Activities inherit from ActionBarActivity and use the support methods.

public class MyActivity extends ActionBarActivity {

@Overrideprotected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.content);

ActionBar bar = getSupportActionBar();bar.setDisplayHomeAsUpEnabled(true);bar.setTitle("Hello DevFest!");

...}

}

Page 14: Android Support Library: Using ActionBarCompat

Usage - ActionBarActivity

ActionBar-related support methods● getSupportActionBar()● supportInvalidateOptionsMenu()● supportRequestWindowFeature() [not in ABS]● setSupportProgress()● setSupportProgressBarIndeterminateVisibility()● startSupportActionMode()

Never call the corresponding native methodsif you use ActionBarCompat!Always call these methods after super.onCreate()

Page 15: Android Support Library: Using ActionBarCompat

Usage - ActionBarActivity

Example - Showing a Progress Barpublic class ProgressActivity extends ActionBarActivity {

...@Overrideprotected 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);

}}

Page 16: Android Support Library: Using ActionBarCompat

Usage - ActionBarActivitySingle Fragment container

Typical codepublic class SingleFragmentActivity extends ActionBarActivity {

@Overrideprotected 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.

Page 17: Android Support Library: Using ActionBarCompat

Usage - ActionBarActivitySingle Fragment container

Universal codepublic class SingleFragmentActivity extends ActionBarActivity {

@Overrideprotected 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();}

}}

Page 18: Android Support Library: Using ActionBarCompat

Usage - ActionBarActivitySingle 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" />

Page 19: Android Support Library: Using ActionBarCompat

Usage - Fragments

Just inherit from the standard Fragment class of the Support Library.

Page 20: Android Support Library: Using ActionBarCompat

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>

Page 21: Android Support Library: Using ActionBarCompat

Usage - Menus

Android 3+ menu items attributes:● showAsAction● actionLayout● actionViewClass● actionProviderClass

Page 22: Android Support Library: Using ActionBarCompat

Usage - Menus

2. Use static methods in MenuItemCompat for Android 3+ MenuItem methods.

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setHasOptionsMenu(true);

}

@Overridepublic void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

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

boolean hasInfoMessage = !TextUtils.isEmpty(message);menu.findItem(R.id.info_message).setVisible(hasInfoMessage)

.setEnabled(hasInfoMessage);

MenuItemCompat.setActionProvider(menu.findItem(R.id.share), new ShareActionProvider(getActivity()));

}

Page 23: Android Support Library: Using ActionBarCompat

Usage - Menus

Android 3+ MenuItem methods:● setActionProvider()● getActionProvider()● setActionView()● getActionView()● expandActionView()● collapseActionView()● isActionViewExpanded()● setOnActionExpandListener()● setShowAsAction()

Page 24: Android Support Library: Using ActionBarCompat

Migrating from ActionBarSherlockto ActionBarCompat

In 7 steps1. Styles resources

Theme.Sherlock.* ➔ Theme.AppCompat.*Widget.Sherlock.* ➔ Widget.AppCompat.*

2. SherlockActivity ➔ ActionBarActivity3. Sherlock*Fragment ➔ *Fragment4. requestWindowFeature() ➔

supportRequestWindowFeature()and move the call after super.onCreate()

Page 25: Android Support Library: Using ActionBarCompat

Migrating from ActionBarSherlockto ActionBarCompat

5. Remove references to the top-level android.R.id.content and use a custom top container layout instead.

6. Menu resourcesReplace the android: namespace with the app local namespace for Android 3+ attributes.

7. Menu items codeReplace the ActionBarSherlock MenuItemswith the native MenuItems+ MenuItemCompat static methods, if needed.

Page 26: Android Support Library: Using ActionBarCompat

Styling Bugs - Issue 58498

1. Too small tabs (on older devices)

Page 27: Android Support Library: Using ActionBarCompat

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>

Page 28: Android Support Library: Using ActionBarCompat

Styling Bugs

2. Landscape glitches (on older devices)

Page 29: Android Support Library: Using ActionBarCompat

2. Landscape glitches (on older devices)

Styling Bugs

Page 30: Android Support Library: Using ActionBarCompat

Styling Bugs

2. Landscape glitches - fix/res/values/styles.xml

<style name="AppTheme" parent="@style/Theme.AppCompat"> ... <item name="android:actionBarStyle"> @style/myapp_transparent_ActionBar</item> <item name="actionBarStyle">@style/myapp_ActionBar</item></style>

<style name="myapp_ActionBar" parent="@style/Widget.AppCompat.ActionBar"> ... <!-- AppCompat fixes for the compatibility ActionBar --> <item name="indeterminateProgressStyle"> @android:style/Widget.ProgressBar.Small</item></style>

Page 31: Android Support Library: Using ActionBarCompat

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.

Page 32: Android Support Library: Using ActionBarCompat

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

Page 33: Android Support Library: Using ActionBarCompat

The End

Thanks for watching!

@BladeCoder - plus.google.com/+ChristopheBeyls