2012-10-17 16 views
11

mam pasek akcji w mojej aplikacji, która wyświetla elementy menu zdefiniowane w moich res/menu/activity_main.xmlAndroid pozycje menu Wyrównaj do lewej w pasku akcji

Moje pozycje menu są wyrównane do prawej na pasku akcji. Chcę, żeby były wyrównane do lewej.

tylko rozwiązania znalazłem do tego używanego paska niestandardowe działania, takie jak ten: Positioning menu items to the left of the ActionBar in Honeycomb

Jednak nie chcę utworzyć niestandardowy układ dla mojego menu. Chcę użyć domyślnych elementów menu wygenerowanych z mojego res/menu/activity_main.xml.

Czy to możliwe?

+4

Możesz zajrzeć do paska akcji Podziel. Użytkownicy Androida znają ikony ActionBar po prawej lub podzielony pasek, który znajduje się u dołu ekranu. Nie chcesz przeprojektowywać czegoś, z czym użytkownicy Androida są już zaznajomieni i czują się komfortowo. http://developer.android.com/guide/topics/ui/actionbar.html#SplitBar – Sababado

+1

Sprawdź ten wpis. To powinno ci pomóc. http://stackoverflow.com/questions/7454102/how-to-align-items-in-action-bar-to-the-left – pepyakin

+0

Nie dostaję lekcji. Chodzi mi o to pytanie jest wystarczająco jasne, jeśli odpowiedź brzmi NIE, to nie sprawia, że ​​pytanie jest złe ... – hendrix

Odpowiedz

0

Można to zrobić tak:

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

I specificaly (bold font) powiedział Nie chcę wyświetlać niestandardowego widoku w pasku akcji ... – hendrix

+0

Nie jest to układ niestandardowy, tylko dodaje parametr układu do istniejącego układu, nie zmienia niczego innego. Ale do tego musi napisać niestandardowy układ, ponieważ inaczej nie będzie w stanie edytować układu. –

+2

Ale jeśli naprawdę musisz to zrobić bez edytowania układu paska akcji, nie będziesz mógł tego zrobić. –

3

Cóż, byłem ciekaw o tym, więc wykopał głęboko wewnątrz źródła w SDK. Kiedyś AppCompatActivity z pozycji 3 menu w jego pliku XML, a ja domyślną metodę onCreateOptionMenu, który był w tym:

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

Po przenieść dalej od sposobu nadmuchać z debuggera, przeszedłem przez następujący stos:

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) 

skończyło się updateMenuView metody BaseMenuPresenter „s, to gdzie revelant praca jest wykonywana.

tejże metody Kod:

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

Tutaj getItemView oraz metody addItemView robić to, co ich Imię powiedzieć. Pierwszy nadmuchuje nowy widok, a drugi dodaje go do rodzica. Co ważniejsze, pod kontrolą debuggera można sprawdzić obiekt nadrzędny, jest to ActionMenuView, który dziedziczy po LinearLayout i zawyżonej formie abc_action_menu_layout.xml.

Oznacza to, że jeśli możesz uzyskać ten widok, możesz zrobić to, co chcesz. Teoretycznie uważam, że można to zrobić z dużą ilością refleksji, ale byłoby to bolesne. Zamiast tego możesz go odtworzyć w swoim kodzie. Implementacje można znaleźć pod numerem here.

Zgodnie z powyższymi pytaniami odpowiedź na twoje pytanie brzmi TAK, można to zrobić, ale będzie to trudne.

Edit:

stworzyłem dowodu koncepcji robi to z refleksji. Użyłem com.android.support:appcompat-v7:23.1.0.

Próbowałem tego na emulatorze (Android 6.0) i na moim Zuk Z1 (CM Android 5.1.1), na oba działa dobrze.

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> 

działaniach w 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> 

aktywny:

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

Chociaż grawitacja została tu zmieniło, na ekranie nie ma żadnego revelant różnica. Aby uzyskać widoczną widoczną zmianę, należy dostosować inne parametry układu (np. Szerokość).

Podsumowując, niestandardowy układ jest znacznie łatwiejszy w użyciu.

Powiązane problemy