2012-10-17 22 views
11

में छोड़ दिया करने के लिए मैं अपने आवेदन है कि मेरे res/menu/activity_main.xmlएंड्रॉयड संरेखित मेनू आइटम कार्रवाई बार

मेरे मेनू आइटम में परिभाषित मेनू आइटम प्रदर्शित करता है कार्रवाई पट्टी पर सही करने के लिए गठबंधन कर रहे हैं में कार्रवाई बार की है। मैं उन्हें बाएं से गठबंधन करना चाहता हूं।

केवल समाधान मैं इस का इस्तेमाल किया कस्टम क्रिया बार के लिए मिल गया है, इस तरह: Positioning menu items to the left of the ActionBar in Honeycomb

हालांकि, मुझे नहीं मेरे मेनू के लिए कस्टम लेआउट बनाना चाहते हैं। मैं अपने res/menu/activity_main.xml से उत्पन्न डिफ़ॉल्ट मेनू आइटम का उपयोग करना चाहता हूं।

क्या यह संभव है?

+4

आप स्प्लिट एक्शन बार में देखना चाहते हैं। एंड्रॉइड उपयोगकर्ता दाईं ओर एक्शनबार आइकन से परिचित हैं, या स्क्रीन के निचले हिस्से में विभाजित बार पर हैं। आप ऐसा कुछ नया स्वरूप नहीं बनाना चाहते हैं जो एंड्रॉइड उपयोगकर्ता पहले ही परिचित और आरामदायक हैं। 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

मुझे डाउनवॉट नहीं मिलते हैं। मेरा मतलब है कि सवाल पर्याप्त है, अगर जवाब नहीं है, तो यह सवाल खराब नहीं करता है ... – 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

ठीक है, मैं इस बारे में उत्सुक था, इसलिए मैं गहरी एसडीके के स्रोत के अंदर खोदा। मैं इसे के एक्सएमएल फ़ाइल में 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 नहीं है अंतर। वास्तविक दृश्य परिवर्तन प्राप्त करने के लिए अन्य लेआउट पैराम (उदाहरण चौड़ाई) को ट्यून किया जाना चाहिए।

सब कुछ, एक कस्टम लेआउट का उपयोग करना बहुत आसान है।

संबंधित मुद्दे