2012-10-17 33 views
11

我必須行動起來吧在我的應用程序,顯示在我的res/menu/activity_main.xmlAndroid的對齊菜單項來留在動作條

我的菜單項中定義的菜單項對齊,以正確的行動吧。我希望他們與左邊對齊。

唯一的解決辦法,我發現這種使用的自定義操作欄,像這樣的: Positioning menu items to the left of the ActionBar in Honeycomb

然而,我不想爲我的菜單創建自定義佈局。我想使用從res/menu/activity_main.xml生成的默認菜單項。

這可能嗎?

+4

您可能想要查看拆分操作欄。 Android用戶熟悉右側的ActionBar圖標或屏幕底部的拆分欄。您不希望重新設計Android用戶已經熟悉和熟悉的內容。 http://developer.android.com/guide/topics/ui/actionbar.html#SplitBar – Sababado

+1

檢查這個職位。它應該幫助你。 http://stackoverflow.com/questions/7454102/how-to-align-items-in-action-bar-to-the-left – pepyakin

+0

我沒有得到downvotes。我的意思是問題很明顯,如果答案是否定的,那不會使問題不好... – hendrix

回答

0

你可以這樣說:

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

我指定了(粗體字體)告訴我不想在操作欄中顯示自定義視圖... – hendrix

+0

這不是自定義佈局,他只是向現有佈局添加布局參數,他不會更改其他內容。但爲此,他必須編寫自定義佈局,否則他將無法編輯佈局。 –

+2

但是,如果您確實需要在沒有任何操作欄佈局編輯的情況下執行此操作,那麼您將無法執行此操作。 –

3

嗯,我很好奇這一點,所以我深挖SDK的源裏面。我用AppCompatActivity在它的XML文件3菜單項,我使用了默認onCreateOptionMenu方法,該方法是這樣的:

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

後,我從與調試器的充氣方法繼續前進,我通過下面的堆棧去:

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) 

它在BaseMenuPresenterupdateMenuView方法結束了,這哪裏是revelant工作已經完成。

該方法的代碼:

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

這裏getItemViewaddItemView方法做他們的名字說什麼。第一個膨脹一個新的視圖,第二個添加到父項。更重要的是,在調試器下可以檢查父對象,這是一個ActionMenuView,它繼承自LinearLayout和虛增形式abc_action_menu_layout.xml

這意味着如果你能得到這個觀點,你可以做你想做的。從理論上講,我認爲這可以通過很多反思來完成,但這會很痛苦。 而不是那個,你可以在你的代碼中重現它。實現可以在here找到。根據上面的內容,你的問題的答案是YES,它可以完成,但它會很棘手。

編輯:

我創建了一個概念證明與反思這樣做。我用過com.android.support:appcompat-v7:23.1.0

我試過這個在模擬器(Android 6.0)和我的Zuk Z1(CM Android 5.1.1),它都工作正常。

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

活動:

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

雖然重心已經改變了這裏,在屏幕上,這並不做任何revelant區別。爲了獲得真正的可見變化,應調整其他佈局參數(例如寬度)。

總而言之,自定義佈局更容易使用。