Android Lollipop,AppCompat ActionBar自定义视图不会占用整个屏幕宽度


97

因此,我刚刚将代码库更新为Lollipop,并且操作栏出现问题。我正在使用AppCompat和ActionBarActivity,并放大自定义视图。自定义视图似乎不再占据屏幕的整个宽度,在左侧留下一条细条

19楼 它过去的样子

21楼 现在的样子

这是我用来设置操作栏的代码。有人有主意吗?

final ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
    actionBar.setDisplayHomeAsUpEnabled(false);
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(true);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setCustomView(R.layout.action_bar_content_search_custom_view);
    actionBar.setBackgroundDrawable(null);
    // actionBar.setStackedBackgroundDrawable(null);
    TextView title = (TextView) actionBar.getCustomView().findViewById(R.id.action_bar_title);
    title.setText(R.string.youtube);
    ImageView back = (ImageView) actionBar.getCustomView().findViewById(R.id.action_bar_back);
    back.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });
}

编辑

现在,取出自定义视图并更改背景会占用整个宽度。因此,问题在于,如何使CustomView占据ActionBar的整个宽度?


如果您暂时注释掉自定义视图部分,它的表现会更好吗?如果没有,我可能倾向于您的主题。
CommonsWare,2014年

我删除了自定义视图,并将其背景设置为ActionBar的背景可绘制对象,并且该背景现在确实占据了整个宽度
Stevie Kideckel 2014年

您可能会在带有和不带有自定义视图的“层次结构视图”中偷看自己的活动,并查看是否可以确定由于自定义视图而正在改变的布局规则。这可能是新版中的错误appcompat-v7
CommonsWare,2014年

在我看来那是预留的地方ImageView。尝试对初学者禁用它。
Nikola Despotoski 2014年

1
嗨,让自定义视图占据整个宽度似乎是一个很好的解决方案。即使设置了布局权重,我也没有扩展。看到这里: stackoverflow.com/a/20794736/581574
ratana 2014年

Answers:


111

看起来这是由于ActionBar最近appcompat-v7更新中的最新更改引起的。似乎应该如何处理操作栏发生了重大变化。

我遇到了同样的问题,在阅读了ActionBar文档之后,尤其是在下面的引文中,我找到了解决方案。

从Android L(API级别21)开始,操作栏可以由应用程序布局内的任何“工具栏”小部件表示。应用程序可以向活动发出信号,将哪个工具栏视为活动的动作栏。使用此功能的活动应使用提供的.NoActionBar主题之一,将windowActionBar属性设置为false,否则不请求窗口功能。

我的看法是,AppCompat主题发生了变化,一方面似乎打破了几件事,但另一方面却提供了更大的灵活性。我建议按照以下步骤操作:

  1. .NoActionBar如上述报价所述,在您的活动中使用样式
  2. 将“”添加android.support.v7.widget.Toolbar到“活动”布局
  3. 设置app:contentInsetStart="0dp"属性。这是您在问题中描述的余量的主要问题
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/actionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentInsetEnd="0dp"
    app:contentInsetStart="0dp" >
</android.support.v7.widget.Toolbar>

通常建议您在一个单独的布局文件中执行此操作,并include在您的活动布局中使用,因此,如果在多个活动中使用,则只需在一个位置自定义工具栏

<include layout="@layout/view_action_bar" />
  1. 使用findViewByIdsetSupportActionBar您的活动onCreate,以signal to the Activity which Toolbar should be treated as the Activity's action bar
Toolbar actionBar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(actionBar);
  1. 完成此操作后,所有添加的操作onCreateOptionsMenu将被添加到工具栏,并将其视为活动操作栏。
  2. 根据需要进一步自定义工具栏(添加子视图等)

1
我正在尝试将工具栏与导航抽屉一起使用,但是出现错误Error inflating class fragment
Ahmed Nawaz 2014年

答案共享所有相关代码。看来您应该针对您的案例提出一个新的问题,因为这似乎是一个不同的问题。
Muzikant 2014年

谢谢。我通过用工具栏替换操作栏解决了问题。
艾哈迈德·纳瓦兹

9
您不应在名称空间声明中使用显式包名称。使用xmlns:app="http://schemas.android.com/apk/res-auto"
2014年

1
不需要setCustomView。只需使用要包含在工具栏中的小部件来构建布局文件(例如,将子视图添加到答案的第3部分中描述的布局文件中)
Muzikant 2014年

51

而不是像Muzikant所说的那样做很多工作并喜欢这个答案

    getSupportActionBar().setDisplayShowHomeEnabled(false);
    getSupportActionBar().setDisplayShowTitleEnabled(false);
    getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
    LayoutInflater mInflater = LayoutInflater.from(this);

    View mCustomView = mInflater.inflate(R.layout.action_bar_home, null);
    getSupportActionBar().setCustomView(mCustomView);
    getSupportActionBar().setDisplayShowCustomEnabled(true);
    Toolbar parent =(Toolbar) mCustomView.getParent();//first get parent toolbar of current action bar 
    parent.setContentInsetsAbsolute(0,0);// set padding programmatically to 0dp

您只需添加最后两行代码即可解决您的问题。

希望对您和其他任何人有帮助。

更新:在对此进行了一些研究之后,我发现此解决方案在某些情况下将不起作用。左侧缝隙(HOME或BACK)将被移除,但右侧缝隙(MENU)将保持不变。以下是这些情况下的解决方案。

View v = getSupportActionBar().getCustomView();
LayoutParams lp = v.getLayoutParams();
lp.width = LayoutParams.MATCH_PARENT;
v.setLayoutParams(lp);

将上述四行添加到上面的代码中,以便右侧间隙也从支撑操作栏上删除。


谢谢!谢谢!最后两行是我一直在寻找的!
digitalmidges

我们在哪里添加这些行?在工具栏部分之后?
2016年

1
@summers是,在工具栏代码后立即添加它们。
Amrut Bidri '16

31

我认为您也可以使用样式。试试这个。在kitkat上测试过

<style name="AppTheme" parent="Theme.AppCompat">
  <item name="toolbarStyle">@style/AppThemeToolbar</item>
</style>

<style name="AppThemeToolbar" parent="Widget.AppCompat.Toolbar" >
  <item name="contentInsetStart">0dp</item>
</style>

1
这个答案是错误的:android:contentInsetStart需要API级别21(当前最小值为14)
mr.boyfox

但是,成语很好!您需要分别为api 21和旧版本编写样式。
mr.boyfox

如果您仍在使用默认操作栏,这是删除左页边距的正确答案。
Tooroop

这确实有效!使用最新版本的支持库,我认为您不需要两次声明属性(android:不必声明)。
BoD

我一直在寻找这个问题,当我找到您的答案时,我发现我已经对其进行了投票!因此,两次感谢。
user1732313 2015年

8

没有其他答案对我有用,因此我查看了在此处找到的实际AppCompat v7样式。

如果您查看Base.Widget.AppCompat.ActionBar样式,则它具有:

<item name="contentInsetStart">@dimen/abc_action_bar_content_inset_material</item>
<item name="contentInsetEnd">@dimen/abc_action_bar_content_inset_material</item>

因此很明显,我们只需要以我们自己的操作栏样式覆盖这些属性:

<style name="ActionBar" parent="@style/Base.Widget.AppCompat.ActionBar">
        <item name="contentInsetStart">0dp</item>
        <item name="contentInsetEnd">0dp</item>
</style>

这对我很有用,希望它对其他人也有帮助。


是的,作为所选答案的状态,关键是ActionBar / Toolbar的contentInsetStart和contentInsetEnd属性。定义自己的样式是有效的,但是您也可以在xml中工具栏的属性上将它们设置为0dp
Stevie Kideckel 2015年

1

在我的头对着显示器跳动很多之后,这对我有用

 Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
        toolbar.setContentInsetStartWithNavigation(0);
        toolbar.setContentInsetEndWithActions(0);
        toolbar.setContentInsetsAbsolute(0, 0);
        toolbar.setPadding(0, 0, 0, 0);

getCustomView()。getParent()是诀窍


0

今天我也刚遇到这个问题,然后我发现res/values-v21/styles.xml我的项目中有一个由Android Studio自动生成的项目,这就是原因。

为什么?

因为我res/values-v21/styles.xml的内容是:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>
</resources>

而我res/values/styles.xml包含的内容如下:

<style name="BaseAppTheme" parent="android:Theme.Holo.Light">
    <!-- Customize your theme here. -->
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:soundEffectsEnabled">false</item>
</style>

然后,当我在Lollipop上运行我的应用程序时,res/values-v21/styles.xml使用了,这引起了OP的确切问题。所以我得出一个简单的解决方法就是删除:

    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>

res/values-v21/styles.xml


0

到这一点:

 ActionBar actionBar = getSupportActionBar();
                actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
                actionBar.setCustomView(R.layout.actionbar_layout);
                Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
                    toolbar.setContentInsetsAbsolute(0, 0);
                    toolbar.setPadding(0, 0, 0, 0);

确保导入正确的工具栏- android.support.v7.widget.Toolbar;


0

在代码之外再写这两行

Toolbar toolbar=(Toolbar)viewActionBar.getParent();
toolbar.setContentInsetsAbsolute(0,0);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.