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.
The overlay is caused due the different resource id used to reference the content view in different versions of Android. Please refer to the post of Shellom for detailed information. Meanwhile, the following snippet should help you to identify the relevant portion of your code.
// http://code.google.com/p/android/issues/detail?id=58108
private static int getContentViewCompat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH ?
android.R.id.content : R.id.action_bar_activity_content;
}
Update: The switch is no longer needed. You can update appcompat-v7 to revision 19.0.0. or newer and then reference android.R.id.content
on all Android versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With