ठीक है, मैं इस बारे में उत्सुक था, इसलिए मैं गहरी एसडीके के स्रोत के अंदर खोदा। मैं इसे के एक्सएमएल फ़ाइल में 3 मेनू आइटम के साथ AppCompatActivity
इस्तेमाल किया, और मैं डिफ़ॉल्ट 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 पाया जा सकता है।
उपर्युक्त चीजों के मुताबिक, आपके प्रश्न का उत्तर हाँ है, यह किया जा सकता है, लेकिन यह मुश्किल होगा।
संपादित करें:
मैं प्रतिबिंब के साथ ऐसा करने के लिए अवधारणा का एक सबूत बनाया। मैंने com.android.support:appcompat-v7:23.1.0
का उपयोग किया है।
मैंने इसे एक एमुलेटर (एंड्रॉइड 6.0) और मेरे ज़ुक जेड 1 (सीएम एंड्रॉइड 5.1.1) पर कोशिश की है, दोनों पर यह ठीक काम करता है।
मेनू एक्सएमएल:
<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 एक्सएमएल:
<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 नहीं है अंतर। वास्तविक दृश्य परिवर्तन प्राप्त करने के लिए अन्य लेआउट पैराम (उदाहरण चौड़ाई) को ट्यून किया जाना चाहिए।
सब कुछ, एक कस्टम लेआउट का उपयोग करना बहुत आसान है।
आप स्प्लिट एक्शन बार में देखना चाहते हैं। एंड्रॉइड उपयोगकर्ता दाईं ओर एक्शनबार आइकन से परिचित हैं, या स्क्रीन के निचले हिस्से में विभाजित बार पर हैं। आप ऐसा कुछ नया स्वरूप नहीं बनाना चाहते हैं जो एंड्रॉइड उपयोगकर्ता पहले ही परिचित और आरामदायक हैं। 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
मुझे डाउनवॉट नहीं मिलते हैं। मेरा मतलब है कि सवाल पर्याप्त है, अगर जवाब नहीं है, तो यह सवाल खराब नहीं करता है ... – hendrix