Android alinea los elementos del menú a la izquierda en la barra de acción

Tengo barra de acción en mi aplicación que muestra los elementos de menú definidos en mi res/menu/activity_main.xml

Mis elementos de menú están alineados a la derecha en la barra de acción. Quiero que estén alineados a la izquierda.

Solamente las soluciones encontré para esta barra de acción personalizada usada, como ésta: Colocando los elementos del menú a la izquierda del ActionBar en Honeycomb

Sin embargo, no quiero crear diseño personalizado para mi menú . Quiero usar los elementos de menú predeterminados generados desde mi res/menu/activity_main.xml .

es posible?

2 Solutions collect form web for “Android alinea los elementos del menú a la izquierda en la barra de acción”

Bueno, tenía curiosidad por esto, así que cavé profundamente en la fuente del SDK. Utilicé AppCompatActivity con 3 elementos de menú en su archivo XML, y usé el método onCreateOptionMenu por onCreateOptionMenu , que era el siguiente:

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

Después de pasar del método inflate con el depurador, pasé por la siguiente pila:

 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) 

Terminó en el método updateMenuView , aquí es donde se realiza el trabajo revelado.

El código del método:

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

Aquí los getItemView y addItemView hacen lo que su nombre dice. La primera infla una nueva vista, y la segunda la agrega a la matriz. Lo que es más importante, bajo el depurador, se puede comprobar el objeto padre, es un ActionMenuView , que hereda de LinearLayout y el formulario inflado abc_action_menu_layout.xml .

Esto significa que si puede obtener esta vista, puede hacer lo que quiera. Teóricamente, creo que se puede hacer con mucha reflexión, pero sería doloroso. En lugar de eso, puede reproducirlo en su código. Las implementaciones se pueden encontrar aquí .

De acuerdo con las cosas de arriba, la respuesta para su pregunta es SI, se puede hacer, pero será complicado.

Editar:

He creado una prueba de concepto para hacer esto con la reflexión. He utilizado com.android.support:appcompat-v7:23.1.0 .

He probado esto en un emulador (Android 6.0) y en mi Zuk Z1 (CM Android 5.1.1), en ambos funciona bien.

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

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

Actividad:

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

Aunque la gravedad se ha cambiado aquí, en la pantalla esto no hace ninguna diferencia real. Para obtener un cambio real visible, deben ajustarse otros parámetros de diseño (por ejemplo, ancho).

Con todo, un diseño personalizado es mucho más fácil de usar.

Puedes hacerlo así:

 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)); 
  • No se puede instanciar la clase android.support.v7.widget.SearchView
  • Desapareciendo el título de la barra de herramientas
  • Estilo de elemento de menú Arc como en la aplicación tumblr para Android
  • Empuja los iconos hacia afuera cuando se expanda la vista de búsqueda en la barra de herramientas de Android
  • Cómo cambiar el color de fondo del menú de opciones de Action Bar en Android 4.2?
  • Cómo centralizar iconos en la barra de herramientas en android studio
  • OnCreateOptionsMenu () en el fragmento que no reemplaza los menús de ActionBar
  • Añadir Spinner a la barra de menús de acción
  • Cómo crear un subnivel en el menú de navegación en android?
  • Reutilizar la barra de acciones en todas las actividades de la aplicación
  • "No se encontró ningún identificador de recurso para el atributo 'showAsAction' en el paquete 'android'"
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.