La vue personnalisée Android Lollipop, AppCompat ActionBar ne prend pas toute la largeur de l'écran

97

Donc, je viens de mettre à jour ma base de code vers Lollipop et j'ai des problèmes avec la barre d'action. J'utilise AppCompat et ActionBarActivity et je gonfle une vue personnalisée. Il semble que la vue personnalisée n'occupe plus toute la largeur de l'écran, laissant une fine bande sur la gauche

Construire avec 19 À quoi il ressemblait

Construire avec 21 À quoi ça ressemble maintenant

C'est le code que j'utilise pour configurer la barre d'action. Quelqu'un a des idées?

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

Éditer

La suppression de la vue personnalisée et la modification de l'arrière-plan occupent désormais toute la largeur. Le problème est donc de savoir comment faire en sorte qu'un CustomView occupe toute la largeur de l'ActionBar?

Stevie Kideckel
la source
Si vous commentez temporairement les parties de vue personnalisées, se comporte-t-il mieux? Sinon, je pencherais vers cela peut-être en raison de votre thème.
CommonsWare
J'ai supprimé la vue personnalisée et défini son arrière-plan comme arrière-plan dessinable de l'ActionBar et l'arrière-plan occupe maintenant toute la largeur
Stevie Kideckel
Vous pouvez jeter un œil à votre activité dans la vue hiérarchique, avec et sans la vue personnalisée, et voir si vous pouvez déterminer les règles de disposition qui changent en raison de la vue personnalisée. Il est possible que ce soit un bogue dans le nouveau appcompat-v7.
CommonsWare
Il me semble que c'est la place réservée à la montée ImageView. Essayez de le désactiver pour commencer.
Nikola Despotoski
1
Salut, il semble que ce soit une bonne solution pour que la vue personnalisée prenne toute la largeur. Je ne le voyais pas en expansion, même avec des pondérations de mise en page définies. voir ici: stackoverflow.com/a/20794736/581574
ratana

Réponses:

111

Il semble que cela soit dû aux dernières modifications apportées à la mise à jour ActionBarrécente appcompat-v7. Il semble qu'il y ait des changements importants dans la façon dont vous devez gérer les barres d'action.

J'ai rencontré le même problème et après avoir lu la ActionBardocumentation , et surtout la citation suivante, j'ai trouvé une solution.

À partir d'Android L (niveau d'API 21), la barre d'action peut être représentée par n'importe quel widget de la barre d'outils dans la présentation de l'application. L'application peut signaler à l'activité quelle barre d'outils doit être traitée comme la barre d'action de l'activité. Les activités qui utilisent cette fonctionnalité doivent utiliser l'un des thèmes .NoActionBar fournis, définir l'attribut windowActionBar sur false ou ne pas demander la fonctionnalité de fenêtre.

À mon avis, les AppCompatthèmes ont été modifiés et d'une part semblaient casser certaines choses mais offrir beaucoup plus de souplesse d'autre part. Je recommande de suivre ces étapes:

  1. Utilisez le .NoActionBarstyle dans votre activité comme décrit dans la citation ci-dessus
  2. Ajouter un android.support.v7.widget.Toolbarà votre disposition d'activité
  3. Définissez l' app:contentInsetStart="0dp"attribut. C'est le principal problème avec la marge que vous décrivez dans votre question
<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>

Il est généralement recommandé de le faire dans un fichier de mise en page séparé et de l'utiliser includedans la mise en page de votre activité afin que vous n'ayez besoin de personnaliser la barre d'outils qu'à un seul endroit si elle est utilisée dans plusieurs activités.

<include layout="@layout/view_action_bar" />
  1. Utilisez findViewByIdet setSupportActionBardans votre activité onCreatepoursignal to the Activity which Toolbar should be treated as the Activity's action bar
Toolbar actionBar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(actionBar);
  1. Une fois que vous faites cela, toutes les actions ajoutées onCreateOptionsMenuseront ajoutées à la barre d'outils et seront traitées comme la barre d'actions d'activité.
  2. Personnalisez davantage la barre d'outils selon vos besoins (ajoutez des vues enfants, etc.)
Muzikant
la source
1
J'essaie d'utiliser la barre d'outils avec le tiroir de navigation mais j'obtiens une erreurError inflating class fragment
Ahmed Nawaz
Tout le code pertinent est partagé sur la réponse. Il semble que vous devriez commencer une nouvelle question pour votre cas car cela semble être un problème différent.
Muzikant
Merci. J'ai résolu le problème en remplaçant la barre d'action par la barre d'outils.
Ahmed Nawaz
9
Vous ne devez pas utiliser de noms de package explicites dans les déclarations d'espace de noms. Utilisationxmlns:app="http://schemas.android.com/apk/res-auto"
Liminal
1
Il n'y a pas besoin de setCustomView. Créez simplement un fichier de mise en page avec les widgets que vous souhaitez inclure dans votre barre d'outils (par exemple, ajoutez des vues enfants au fichier de mise en page décrit dans la section 3 de la réponse)
Muzikant
51

Au lieu de faire autant de travail comme mentionné par Muzikant et comme cette réponse

    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

Vous devez ajouter uniquement les deux dernières lignes de code pour résoudre votre problème.

J'espère que cela pourrait vous aider, vous et n'importe qui d'autre.

MISE À JOUR: Après avoir fait quelques recherches à ce sujet, j'ai constaté que cette solution ne fonctionnera pas dans certains cas. L'écart du côté gauche (HOME ou BACK) sera supprimé avec cela, mais l'espace du côté droit (MENU) restera tel quel. Voici la solution dans ces cas.

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

Ajoutez ces quatre lignes au code ci-dessus, de sorte que l'espace du côté droit soit également supprimé de la barre d'action de support.

Amrut Bidri
la source
Merci! Merci! les 2 dernières lignes étaient ce que je cherchais!
ponts numériques
Où ajoutons-nous ces lignes? Après la partie Toolbar?
Zen
1
@summers oui, ajoutez-les immédiatement après le code de la barre d'outils.
Amrut Bidri
31

Je pense que vous pouvez aussi le faire dans les styles. essaye ça. testé sur 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>
GDA
la source
1
Cette réponse est fausse: android: contentInsetStart nécessite le niveau d'API 21 (le minimum actuel est de 14)
mr.boyfox
Mais, idiome très bon! Vous devez écrire le style séparément pour l'API 21 et les anciennes versions.
mr.boyfox
C'est la bonne réponse pour supprimer la marge de gauche si vous utilisez toujours la barre d'action par défaut.
Tooroop
Cela fonctionne vraiment! Avec la dernière version de la bibliothèque de support, je pense que vous n'avez pas besoin de déclarer les attributs deux fois (les attributs android: ne sont pas nécessaires).
BoD
J'ai cherché ce problème et quand j'ai trouvé votre réponse, je vois que je l'ai déjà voté pour! Alors merci deux fois.
user1732313
8

Aucune des autres réponses n'a fonctionné pour moi, j'ai donc jeté un coup d'œil aux styles AppCompat v7 réels, trouvés ici .

Si vous regardez le style Base.Widget.AppCompat.ActionBar, il a:

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

Donc, évidemment, nous avons juste besoin de remplacer ces propriétés dans notre propre style de barre d'action:

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

Cela a très bien fonctionné pour moi, j'espère que cela aidera les autres aussi.

Justin
la source
Oui, comme l'indique la réponse choisie, la clé est les attributs contentInsetStart et contentInsetEnd de l'ActionBar / Toolbar. Il est valide de définir votre propre style, mais vous pouvez également les définir sur 0dp sur les attributs de la barre d'outils dans votre xml
Stevie Kideckel
1

Après m'être beaucoup cogné la tête contre le moniteur, cela a fonctionné pour moi

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

Le getCustomView (). GetParent () est ce qui a fait l'affaire

user330844
la source
0

Je viens de rencontrer ce problème aujourd'hui, puis j'ai découvert que j'avais à l' res/values-v21/styles.xmlintérieur de mon projet qui était généré automatiquement par Android Studio et c'est la cause.

Pourquoi?

Parce que res/values-v21/styles.xmlle contenu de mon était:

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

Et mon res/values/styles.xmlcontenu quelque chose comme:

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

Ensuite, lorsque j'ai exécuté mon application sur Lollipop, le a res/values-v21/styles.xmlété utilisé, et cela a causé exactement le problème qu'OP avait. Je suis donc arrivé à un correctif simple qui consiste simplement à supprimer:

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

dans res/values-v21/styles.xml

Leo
la source
0

jusqu'au point:

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

assurez-vous d'importer la bonne barre d'outils - android.support.v7.widget.Toolbar;

Salman Anjum
la source
0

Écrivez ces deux lignes en plus avec votre code

Toolbar toolbar=(Toolbar)viewActionBar.getParent();
toolbar.setContentInsetsAbsolute(0,0);
Anisuzzaman Babla
la source