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

Я видалив спеціальний вигляд і встановив його фон як фон, що малюється в ActionBar, а фон зараз займає всю ширину
— Stevie Kideckel

Ви можете зазирнути до своєї діяльності в режимі перегляду ієрархії, як зі спеціальним представленням, так і без нього, і побачити, чи можете ви визначити, які правила компонування зміщуються в результаті користувацького перегляду. Цілком можливо, що це помилка в новому appcompat-v7.
— CommonsWare

Мені здається, це місце, зарезервоване для ImageView. Спробуйте відключити його для початку.
— Микола Деспотоскі

1
Привіт, здається, це хороше рішення, щоб користувацький перегляд зайняв всю ширину. Я відчував, що це не розширюється, навіть із встановленими вагами. дивіться тут: stackoverflow.com/a/20794736/581574
— Ratana

Відповіді:


111

Схоже, це викликано останніми змінами до ActionBarостаннього appcompat-v7оновлення. Здається, що в тому, як слід поводитись із панелями дій, є суттєві зміни.

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

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

Як я це бачу, 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. Використовуйте findViewByIdта setSupportActionBarу своїй діяльності 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
— Ахмед Наваз

Весь відповідний код ділиться у відповіді. Схоже, ви повинні почати нове запитання для своєї справи, оскільки це здається іншою проблемою.
— Музикант

Дякую. Я вирішив проблему, замінивши панель дій на Панель інструментів.
— Ахмед Наваз

9
Не слід використовувати явні назви пакунків у деклараціях простору імен. Використанняxmlns:app="http://schemas.android.com/apk/res-auto"
— Liminal

1
У цьому немає потреби setCustomView. Просто побудуйте файл макета з віджетами, які ви хочете включити на панель інструментів (наприклад, додайте дочірні подання у файл макета, описаний у розділі 3 відповіді)
— Muzikant

51

Замість того, щоб робити стільки роботи, як згадував Музикант, і ця відповідь подобається

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

Додайте ці чотири рядки до вищевказаного коду, щоб правий бічний розрив також був видалений з панелі дій підтримки.


Дякую! Дякую! останні 2 рядки було те, що я шукав!
— digitalmidges

Де ми додаємо ці рядки? Після частини Панелі інструментів?
— Дзен

1
@summers так, додайте їх відразу після коду панелі інструментів.
— Amrut Bidri

31

Я думаю, ви також можете це робити в стилях. спробуйте це. випробували його на киткаті

<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

Це справді працює! З останньою версією підтримки lib, я думаю, вам не потрібно декларувати атрибути двічі (android: ті не потрібні).
— BoD

Я шукав цю проблему, і коли я знайшов вашу відповідь, я бачу, що я вже її схвалив! Тож двічі дякую.
— користувач1732313

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>

Це спрацювало чудово для мене, сподіваюся, що це допомагає і іншим.


Так, як зазначено у вибраній відповіді, ключовим є атрибути contentInsetStart та contentInsetEnd на панелі дій / панелі інструментів. Дійсно визначити власний стиль, але ви також можете встановити їх на 0dp на атрибутах Панелі інструментів у вашому xml
— Stevie Kideckel

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було використано, і це спричинило точну проблему, що була в ОП. Тому я прийшов до простого виправлення - це просто видалення:

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.