嗯,我很好奇這一點,所以我深挖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)
它在BaseMenuPresenter
的updateMenuView
方法結束了,這哪裏是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++;
}
}
}
這裏getItemView
和addItemView
方法做他們的名字說什麼。第一個膨脹一個新的視圖,第二個添加到父項。更重要的是,在調試器下可以檢查父對象,這是一個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區別。爲了獲得真正的可見變化,應調整其他佈局參數(例如寬度)。
總而言之,自定義佈局更容易使用。
您可能想要查看拆分操作欄。 Android用戶熟悉右側的ActionBar圖標或屏幕底部的拆分欄。您不希望重新設計Android用戶已經熟悉和熟悉的內容。 http://developer.android.com/guide/topics/ui/actionbar.html#SplitBar – Sababado
檢查這個職位。它應該幫助你。 http://stackoverflow.com/questions/7454102/how-to-align-items-in-action-bar-to-the-left – pepyakin
我沒有得到downvotes。我的意思是問題很明顯,如果答案是否定的,那不會使問題不好... – hendrix