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.