在appcompat中使用ActionBar的自定义布局会导致内容与操作栏重叠

时间:2013-10-28 12:57:35

标签: android android-actionbar android-appcompat

我已使用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
                              )
                             );
  }
}

我的活动只是一个愚蠢的ActionBarActivity,它会在FrameLayout中加载一个片段。这是片段代码:

@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;
}

这是操作栏布局:

<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>

以下是两个按钮:

<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>

<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>

这是Jelly Bean与Gingerbread的结果(第一个是Galaxy Nexus,后者是模拟器):

ActionBar compat with Gingerbread overlap bug

对于质量感到抱歉,动画PNG无法正常工作,所以我切换到动画GIF。

如您所见,内容布局覆盖了操作栏自定义布局(注意JB和滚动条位置的蓝色溢出)。

使用非自定义操作栏布局在JB和GB上都能正常工作。

1 个答案:

答案 0 :(得分:1)

叠加是由于在不同版本的Android中用于引用内容视图的不同资源ID引起的。请参阅post of Shellom for detailed information。同时,以下代码段可以帮助您识别代码的相关部分。

// 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;
}

更新:不再需要切换。您可以将 appcompat-v7更新为修订版19.0.0。或更新版本,然后在所有Android版本上引用android.R.id.content

相关问题