Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


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.

  • Rellenar lista de vista personalizada mediante ListFragment
  • No se puede emitir a la clase ViewPager personalizada
  • Discurso a texto en Android
  • Android: valor predeterminado en editText
  • Servicio de fondo con oyente de localización en android
  • Android RelativeLayout - cómo posicionar?
  • 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?

  • ¿Hay algún punto de una actividad con un fragmento?
  • Release AudioRecord android cuando otra solicitud de aplicación para la grabación
  • ¿Por qué falla Adb con el error ?
  • ¿Cuál es el mejor lenguaje para la programación gráfica en tiempo real en Android?
  • Cómo probar la aplicación bluetooth en los emuladores en android
  • ¿El emulador de Android admite OpenGL ES 3.0?
  • 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)); 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.