Android Lollipop, AppCompat ActionBar пользовательский вид не занимает всю ширину экрана

Итак, я просто обновил свою кодовую базу до Lollipop, и у меня возникли проблемы с панелью действий. Я использую AppCompat и ActionBarActivity и раздуваю пользовательский вид. Кажется, что пользовательский вид больше не занимает всю ширину экрана, оставляя тонкую полосу слева

Building with 19 Как это выглядело

Building with 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();
        }
    });
}

Edit

Извлечение пользовательского представления и изменение фона теперь занимает всю ширину. Таким образом, проблема заключается в том, как мы можем сделать CustomView занимать всю ширину ActionBar?

Ответ 1

Похоже, что это вызвано последними изменениями в ActionBar в недавнем обновлении appcompat-v7. Похоже, что есть существенные изменения в том, как вы должны обрабатывать панели действий.

У меня возникла такая же проблема, и после прочтения ActionBar документации, и особенно следующая цитата, я нашел решение.

Начиная с Android L (уровень API 21), панель действий может быть представлена ​​любым виджнем панели инструментов в макете приложения. Приложение может сигнализировать о том, какую панель инструментов следует рассматривать как панель действий "Действие". Действия, в которых используется эта функция, должны использовать одну из предоставленных тем .NoActionBar, установить атрибут windowActionBar в false или иначе не запрашивать функцию окна.

То, как я это вижу, темы AppCompat были изменены и, с одной стороны, казалось, сломал несколько вещей, но обеспечил гораздо большую гибкость с другой. Я рекомендую выполнить следующие действия:

  • Используйте стиль .NoActionBar в своей деятельности, как описано в приведенной выше цитате.
  • Добавить android.support.v7.widget.Toolbar в макет вашей деятельности
  • Установите атрибут 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. Используйте findViewById и setSupportActionBar в вашей деятельности onCreate - signal to the Activity which Toolbar should be treated as the Activity action bar
Toolbar actionBar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(actionBar);
  1. После этого все действия, добавленные в onCreateOptionsMenu, будут добавлены на панель инструментов и будут рассматриваться как панель действий.
  2. Далее настройте панель инструментов по желанию (добавьте дочерние представления и т.д.).

Ответ 2

Вместо того, чтобы выполнять такую ​​большую работу, как упоминалось 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);

Добавьте эти четыре строки в код выше, так что правый боковой зазор также будет удален из панели действий.

Ответ 3

Я думаю, вы также можете сделать это в стилях. попробуй это. протестировал его на 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>

Ответ 4

Ни один из других ответов не работал у меня, поэтому я взглянул на фактические стили 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>

Это отлично поработало для меня, надеюсь, что это тоже поможет другим.

Ответ 5

Я тоже столкнулся с этой проблемой сегодня, тогда я узнал, что у меня есть 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>

in res/values-v21/styles.xml

Ответ 6

После того, как я сильно ударил головой о монитор, это сработало для меня.

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

getCustomView(). getParent() - вот что сделал трюк