Android aligner les éléments du menu à gauche dans la barre d'action

J'ai une barre d'action dans ma application qui affiche les éléments de menu définis dans ma res/menu/activity_main.xml

Mes éléments de menu sont alignés vers la droite sur la barre d'action. Je veux qu'ils soient alignés sur la gauche.

  • Comment puis-je avoir OnClickListener fonctionnant sur une vue personnalisée avec RelativeLayout?
  • Comment implémenter un auditeur
  • Android: supprimer la marge gauche de la mise en page personnalisée de la barre d'action
  • Dialogue de numérotation de numérotation Android
  • FragmentPagerAdapter - Comment gérer les changements d'orientation?
  • Dispositif Android LogCat déconnecté
  • Seules les solutions que j'ai trouvées pour cette barre d'action personnalisée utilisée, comme celle-ci: Positionner les éléments du menu à gauche de ActionBar dans Honeycomb

    Cependant, je ne veux pas créer de mise en page personnalisée pour mon menu . Je souhaite utiliser les éléments de menu par défaut générés à partir de mes res/menu/activity_main.xml .

    Est-ce possible?

  • Paiement Paypal: comment obtenir une demande de réussite lors du chargement du paypal dans la visualisation web
  • Ajouter l'écran de chargement lors du démarrage de l'application Android
  • Modifier le thème d'un ListFragment pour être différent de l'activité?
  • Contenu WebView clair
  • Désactivez le zoom lorsque vous cliquez sur les champs de formulaire dans une page Web?
  • Android - java.lang.IllegalArgumentException: contentIntent erreur requise par notification?
  • 2 Solutions collect form web for “Android aligner les éléments du menu à gauche dans la barre d'action”

    Eh bien, j'étais curieux à ce sujet, alors j'ai creusé au fond de la source du SDK. J'ai utilisé AppCompatActivity avec 3 éléments de menu dans son fichier XML, et j'ai utilisé la méthode par défaut onCreateOptionMenu , ce qui était le suivant:

      @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } 

    Après que je passe de la méthode de gonflage avec le débogueur, je suis passé par la pile suivante:

     updateMenuView():96, BaseMenuPresenter (android.support.v7.internal.view.menu) updateMenuView():231, ActionMenuPresenter (android.support.v7.widget) dispatchPresenterUpdate():284, MenuBuilder (android.support.v7.internal.view.menu) onItemsChanged():1030, MenuBuilder (android.support.v7.internal.view.menu) startDispatchingItemsChanged():1053, MenuBuilder (android.support.v7.internal.view.menu) preparePanel():1303, AppCompatDelegateImplV7 (android.support.v7.app) doInvalidatePanelMenu():1541, AppCompatDelegateImplV7 (android.support.v7.app) access$100():92, AppCompatDelegateImplV7 (android.support.v7.app) run():130, AppCompatDelegateImplV7$1 (android.support.v7.app) handleCallback():739, Handler (android.os) dispatchMessage():95, Handler (android.os) loop():148, Looper (android.os) main():5417, ActivityThread (android.app) invoke():-1, Method (java.lang.reflect) run():726, ZygoteInit$MethodAndArgsCaller (com.android.internal.os) main():616, ZygoteInit (com.android.internal.os) 

    Il s'est terminé par la méthode updateMenuView , c'est là que se déroule la révélation.

    Le code de la méthode:

      public void updateMenuView(boolean cleared) { final ViewGroup parent = (ViewGroup) mMenuView; if (parent == null) return; int childIndex = 0; if (mMenu != null) { mMenu.flagActionItems(); ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems(); final int itemCount = visibleItems.size(); for (int i = 0; i < itemCount; i++) { MenuItemImpl item = visibleItems.get(i); if (shouldIncludeItem(childIndex, item)) { final View convertView = parent.getChildAt(childIndex); final MenuItemImpl oldItem = convertView instanceof MenuView.ItemView ? ((MenuView.ItemView) convertView).getItemData() : null; final View itemView = getItemView(item, convertView, parent); if (item != oldItem) { // Don't let old states linger with new data. itemView.setPressed(false); ViewCompat.jumpDrawablesToCurrentState(itemView); } if (itemView != convertView) { addItemView(itemView, childIndex); } childIndex++; } } } // Remove leftover views. while (childIndex < parent.getChildCount()) { if (!filterLeftoverView(parent, childIndex)) { childIndex++; } } } 

    Ici, les getItemView et addItemView font ce que leur nom dit. Le premier gonfle une nouvelle vue, et la seconde l'ajoute à la parenté. Ce qui est plus important, sous le débogueur, l'objet parent peut être vérifié, c'est ActionMenuView , qui hérite du LinearLayout et du formulaire gonflé abc_action_menu_layout.xml .

    Cela signifie que si vous pouvez obtenir cette vue, vous pouvez faire ce que vous voulez. Théoriquement, je pense que cela peut être fait avec beaucoup de réflexion, mais cela serait douloureux. Au lieu de cela, vous pouvez le reproduire dans votre code. Des implémentations peuvent être trouvées ici .

    Selon les éléments ci-dessus, la réponse à votre question est OUI, cela peut être fait, mais ce sera délicat.

    Modifier:

    J'ai créé une preuve de concept pour faire cela avec réflexion. J'ai utilisé com.android.support:appcompat-v7:23.1.0 .

    J'ai essayé cela sur un émulateur (Android 6.0) et sur mon Zuk Z1 (CM Android 5.1.1), il fonctionne bien.

    Menu XML:

     <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_settings" android:title="@string/action_settings" android:orderInCategory="100" app:showAsAction="always" /> <item android:id="@+id/action_settings2" android:title="TEST1" android:orderInCategory="100" app:showAsAction="always" /> <item android:id="@+id/action_settings3" android:title="TEST2" android:orderInCategory="100" app:showAsAction="always" /> </menu> 

    Activty XML:

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button" android:layout_gravity="center_vertical" /> </LinearLayout> 

    Activité:

     public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //only a linear layout with one button setContentView(R.layout.activity_main2); Button b = (Button) findViewById(R.id.button); // do the whole process for a click, everything is inited so we dont run into NPE b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AppCompatDelegate delegate = getDelegate(); Class delegateImpClass = null; Field menu = null; Method[] methods = null; try { //get objects based on the stack trace delegateImpClass = Class.forName("android.support.v7.app.AppCompatDelegateImplV7"); //get delegate->mPreparedPanel Field mPreparedPanelField = delegateImpClass.getDeclaredField("mPreparedPanel"); mPreparedPanelField.setAccessible(true); Object mPreparedPanelObject = mPreparedPanelField.get(delegate); //get delegate->mPreparedPanel->menu Class PanelFeatureStateClass = Class.forName("android.support.v7.app.AppCompatDelegateImplV7$PanelFeatureState"); Field menuField = PanelFeatureStateClass.getDeclaredField("menu"); menuField.setAccessible(true); Object menuObjectRaw = menuField.get(mPreparedPanelObject); MenuBuilder menuObject = (MenuBuilder) menuObjectRaw; //get delegate->mPreparedPanel->menu->mPresenter(0) Field mPresentersField = menuObject.getClass().getDeclaredField("mPresenters"); mPresentersField.setAccessible(true); CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters = (CopyOnWriteArrayList<WeakReference<MenuPresenter>>) mPresentersField.get(menuObject); ActionMenuPresenter presenter0 = (ActionMenuPresenter) mPresenters.get(0).get(); //get the view from the presenter Field mMenuViewField = presenter0.getClass().getSuperclass().getDeclaredField("mMenuView"); mMenuViewField.setAccessible(true); MenuView menuView = (MenuView) mMenuViewField.get(presenter0); ViewGroup menuViewParentObject = (ViewGroup) ((View) menuView); //check the menu items count int a = menuViewParentObject.getChildCount(); Log.i("ChildNum", a + ""); //set params as you want Toolbar.LayoutParams params = (Toolbar.LayoutParams) menuViewParentObject.getLayoutParams(); params.gravity = Gravity.LEFT; menuViewParentObject.setLayoutParams(params); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } } 

    Bien que la gravité ait été modifiée ici, sur l'écran, cela ne modifie rien. Pour obtenir un réel changement visible, d'autres paramètres de mise en page (par exemple, la largeur) doivent être réglés.

    Dans l'ensemble, une mise en page personnalisée est beaucoup plus facile à utiliser.

    Vous pouvez le faire comme ceci:

     activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM); activity.getActionBar().setCustomView(mAutoSyncSwitch, new ActionBar.LayoutParams( ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT)); 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.