自定义ActionBar添加菜单项后标题偏移,如何保持标题居中?
解决ActionBar标题居中被菜单项挤压偏移的问题
这个问题我做项目时也碰到过,核心原因是默认的ActionBar菜单项会抢占布局空间,导致你的自定义标题布局被挤压偏移。下面给你两种可靠的解决方案,亲测有效:
方案一:用ConstraintLayout构建自定义ActionBar(推荐)
ConstraintLayout能精准控制各控件的位置关系,确保标题始终占据左右元素之间的全部空间并居中。
1. 自定义ActionBar布局文件(res/layout/action_bar_custom.xml)
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:background="?attr/colorPrimary"> <!-- 左侧菜单按钮(替代默认menu的左侧item,更可控) --> <ImageView android:id="@+id/iv_left_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_menu" android:padding="8dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> <!-- 居中的应用名称:用0dp宽度填充左右控件间的所有空间,gravity确保文字居中 --> <TextView android:id="@+id/tv_app_title" android:layout_width="0dp" android:layout_height="wrap_content" android:text="你的应用名称" android:textColor="@android:color/white" android:textSize="20sp" android:textStyle="bold" android:gravity="center" app:layout_constraintLeft_toRightOf="@id/iv_left_menu" app:layout_constraintRight_toLeftOf="@id/btn_right_action" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:paddingHorizontal="16dp"/> <!-- 右侧自定义按钮 --> <Button android:id="@+id/btn_right_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="操作" android:textColor="@android:color/white" android:background="?attr/selectableItemBackgroundBorderless" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
2. 在Activity中配置自定义ActionBar
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { // 隐藏默认的系统标题,避免和自定义标题冲突 actionBar.setDisplayShowTitleEnabled(false); // 启用自定义视图 actionBar.setDisplayShowCustomEnabled(true); // 加载并设置自定义布局 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View customActionBar = inflater.inflate(R.layout.action_bar_custom, null); actionBar.setCustomView(customActionBar); // 给左右按钮添加点击事件 ImageView leftMenuBtn = customActionBar.findViewById(R.id.iv_left_menu); Button rightActionBtn = customActionBar.findViewById(R.id.btn_right_action); leftMenuBtn.setOnClickListener(v -> { // 这里可以打开选项菜单,或者执行你的左侧菜单逻辑 openOptionsMenu(); }); rightActionBtn.setOnClickListener(v -> { // 右侧按钮的点击逻辑 }); } } // 如果需要保留更多选项的菜单,依然可以重写这个方法 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.your_menu_file, menu); return true; }
方案二:用LinearLayout配合权重实现
如果不想用ConstraintLayout,LinearLayout的权重属性也能实现同样效果:
自定义ActionBar布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingHorizontal="16dp" android:background="?attr/colorPrimary" android:gravity="center_vertical"> <!-- 左侧菜单按钮 --> <ImageView android:id="@+id/iv_left_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_menu" android:padding="8dp"/> <!-- 居中标题:layout_weight=1 占据剩余所有空间,gravity确保文字居中 --> <TextView android:id="@+id/tv_app_title" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="你的应用名称" android:textColor="@android:color/white" android:textSize="20sp" android:textStyle="bold" android:gravity="center"/> <!-- 右侧自定义按钮 --> <Button android:id="@+id/btn_right_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="操作" android:textColor="@android:color/white" android:background="?attr/selectableItemBackgroundBorderless"/> </LinearLayout>
Activity中的配置和方案一完全一致,这里就不再重复了。
关键原理说明
之前你的标题偏移,是因为标题控件的宽度是wrap_content或者固定值,当左侧菜单项出现时,会抢占布局空间,把标题挤到右边。而上面两种方案的核心是:
- 让标题控件占据左右元素之间的全部可用空间(ConstraintLayout的0dp宽度/LinearLayout的权重)
- 同时设置标题文字的
gravity="center",确保文字在控件内部居中
这样不管左右有没有菜单项/按钮,标题都会始终保持在ActionBar的视觉中心。
内容的提问来源于stack exchange,提问作者Keselme
相关产品推荐
相关产品推荐

