I have implemented a custom action bar layout with AppCompat
:
public class DoneBarActivity {
public interface OnSaveActionListener {
public void onSave();
}
public static void setupActionBar(final ActionBarActivity activity,
final OnSaveActionListener listener) {
// Inflate a "Done/Cancel" custom action bar view.
final LayoutInflater inflater = (LayoutInflater) activity
.getSupportActionBar().getThemedContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View customActionBarView = inflater.inflate(
R.layout.actionbar_custom_view_done_cancel, null);
customActionBarView.findViewById(R.id.actionbar_done)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// "Done" (or "Save")
if (listener != null) {
listener.onSave();
}
activity.finish();
}
});
customActionBarView.findViewById(R.id.actionbar_cancel)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// "Cancel"
activity.finish();
}
});
// Show the custom action bar view and
// hide the normal Home icon and title.
final ActionBar actionBar = activity.getSupportActionBar();
actionBar.setDisplayOptions(
ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM |
ActionBar.DISPLAY_SHOW_HOME |
ActionBar.DISPLAY_SHOW_TITLE);
actionBar.setCustomView(customActionBarView,
new ActionBar.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
);
}
}
My activity is just a dumb ActionBarActivity
that loads a fragment in a FrameLayout
. Here's the fragment code:
@Override
public View onCreateView(final LayoutInflater inflater,
final ViewGroup container,
final Bundle savedInstanceState) {
// ...
DoneBarActivity.setupActionBar((ActionBarActivity) getActivity(),
new DoneBarActivity.OnSaveActionListener() {
@Override
public void onSave() {
saveIssueChangesAndClose();
}
});
return v;
}
Here's the action bar layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:divider="?attr/dividerVertical"
android:showDividers="middle"
android:dividerPadding="12dp">
<include layout="@layout/include_cancel_button"/>
<include layout="@layout/include_done_button"/>
</LinearLayout>
Here are the two buttons:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?actionButtonStyle"
android:id="@+id/actionbar_cancel"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView
style="?actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="20dp"
android:drawableLeft="@drawable/ic_action_cancel"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="@android:string/cancel"/>
</FrameLayout>
and
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?actionButtonStyle"
android:id="@+id/actionbar_done"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<TextView
style="?actionBarTabTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="20dp"
android:drawableLeft="@drawable/ic_action_done"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:text="@string/save"/>
</FrameLayout>
Here's the result in Jelly Bean vs. Gingerbread (Galaxy Nexus for the first, emulator for the latter):
Sorry for the quality, the animated PNG didn't work properly so I switched to animated GIF.
As you can see, the content layout is going over the action bar custom layout (notice the blue overflow in JB and scrollbar position).
Using a non-custom action bar layout works properly on both JB and GB.