विकल्प मेनू की पृष्ठभूमि का रंग कैसे बदलें?


96

मैं विकल्प मेनू के लिए डिफ़ॉल्ट रंग बदलने की कोशिश कर रहा हूं जो सफेद है: मैं विकल्प मेनू पर प्रत्येक आइटम के लिए एक काली पृष्ठभूमि चाहता हूं।

मैंने एंड्रॉइड जैसे कुछ शूट करने की कोशिश की है: मेनू तत्व के भीतर आइटम तत्व पर itemBackground = "# 000000"। लेकिन यह काम नहीं किया।

मैं यह कैसे हासिल कर सकता हूं?



सबसे अच्छा तरीका यहाँ है stackoverflow.com/questions/3519277/…
user3156040

जवाबों:


65

सभी विकल्पों को आज़माने में काफी समय व्यतीत करने के बाद, ओवरफ्लो मेनू बैकग्राउंड को बदलने के लिए AppCompat v7 का उपयोग करके मैं एक ऐप प्राप्त करने में सक्षम था, जो आइटम बैकग्राउंड विशेषता का उपयोग कर रहा था:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="android:itemBackground">@color/overflow_background</item>
    ...
</style>

एपीआई 4.2 से 5.0 तक परीक्षण किया गया।


2
यह स्वीकृत उत्तर, आसान और सरल होना चाहिए।
एलेक्स अर्दाविन

3
लेकिन यह तरंग प्रभाव को हटा देता है: / वैसे भी इसे वापस लगाने के लिए?
डेविड वेलास्केज़

मैं पूरे विंडो बैकग्राउंड को बदलना चाहता हूं, अलग-अलग आइटम बैकग्राउंड को नहीं, उदाहरण के लिए यह प्रत्येक आइटम में बॉर्डर जोड़ देगा यदि आप ऐसी बैकग्राउंड (बॉर्डर के साथ) सेट करते हैं ...
user25

1
मेनू पाठ रंग के बारे में क्या?
डॉक्टरराम

51

यह स्पष्ट रूप से एक समस्या है जो बहुत सारे प्रोग्रामर के पास है और जिसके लिए Google को अभी तक एक संतोषजनक, समर्थित समाधान प्रदान करना है।

इस विषय पर पोस्ट के आसपास बहुत सारे अभिप्रेरित इरादे और गलतफहमी हैं, इसलिए जवाब देने से पहले कृपया इस पूरे उत्तर को पढ़ें।

नीचे मैं इस पृष्ठ पर अन्य उत्तरों से हैक के एक अधिक "परिष्कृत" और अच्छी तरह से टिप्पणी किए गए संस्करण को शामिल करता हूं, इन बहुत ही निकट से संबंधित प्रश्नों से विचारों को भी शामिल करता है:

एंड्रॉइड मेनू का पृष्ठभूमि रंग बदलें

विकल्प मेनू की पृष्ठभूमि का रंग कैसे बदलें?

Android: अनुप्रयोग के मेनू (जैसे पृष्ठभूमि रंग) को अनुकूलित करें

http://www.macadamian.com/blog/post/android_-_theming_the_unthemable/

Android MenuItem टॉगल बटन

क्या Android विकल्प मेनू पृष्ठभूमि को गैर-पारभासी बनाना संभव है?

http://www.codeproject.com/KB/android/AndroidMenusMyWay.aspx

अपारदर्शी होने के लिए मेनू पृष्ठभूमि की स्थापना

मैंने इस हैक को 2.1 (सिम्युलेटर), 2.2 (2 वास्तविक डिवाइस), और 2.3 (2 वास्तविक डिवाइस) पर परीक्षण किया। मेरे पास अभी तक परीक्षण करने के लिए कोई 3.X गोलियां नहीं हैं, लेकिन जब / जब मैं यहां कोई आवश्यक परिवर्तन पोस्ट करूंगा। यह देखते हुए कि 3.X गोलियाँ विकल्प मेनू के बजाय एक्शन बार्स का उपयोग करती हैं, जैसा कि यहाँ बताया गया है:

http://developer.android.com/guide/topics/ui/menus.html#options-menu

यह हैक लगभग निश्चित रूप से 3.X टैबलेट पर कुछ भी नहीं (कोई नुकसान नहीं और अच्छा नहीं) करेगा।

समस्या का विवरण (इसे नकारात्मक टिप्पणी के साथ ट्रिगर-उत्तर देने से पहले पढ़ें):

विकल्प मेनू में विभिन्न उपकरणों पर अलग-अलग शैली है। कुछ पर सफेद पाठ के साथ शुद्ध काला, कुछ पर काले पाठ के साथ शुद्ध सफेद। मैं और कई अन्य डेवलपर्स विकल्प मेनू कोशिकाओं के पृष्ठभूमि रंग के साथ-साथ विकल्प मेनू पाठ के रंग को नियंत्रित करना चाहते हैं ।

कुछ ऐप डेवलपर्स को केवल सेल बैकग्राउंड कलर (टेक्स्ट कलर नहीं) सेट करने की आवश्यकता होती है, और वे इसे एंड्रॉइड का उपयोग करके एक क्लीनर तरीके से कर सकते हैं: एक अन्य उत्तर में वर्णित पैनलफ्लेकबैकग्राउंड स्टाइल। हालाँकि, वर्तमान में शैलियों के साथ विकल्प मेनू पाठ रंग को नियंत्रित करने का कोई तरीका नहीं है, और इसलिए केवल पृष्ठभूमि को दूसरे रंग में बदलने के लिए इस पद्धति का उपयोग कर सकते हैं जो पाठ को "गायब" नहीं करेगा।

हम इसे एक प्रलेखित, भविष्य-प्रूफ समाधान के साथ करना पसंद करेंगे, लेकिन एक बस एंड्रॉइड <= 2.3 के रूप में उपलब्ध नहीं है। इसलिए हमें एक समाधान का उपयोग करना होगा जो वर्तमान संस्करणों में काम करता है और भविष्य के संस्करणों में दुर्घटनाग्रस्त होने / टूटने की संभावना को कम करने के लिए बनाया गया है। हम ऐसा समाधान चाहते हैं जो विफल होने पर गल्ती से डिफ़ॉल्ट व्यवहार में वापस आ जाए।

ऐसे कई वैध कारण हैं कि किसी को विकल्प मेनू के लुक को नियंत्रित करने की आवश्यकता हो सकती है (आमतौर पर बाकी ऐप के लिए एक दृश्य शैली से मेल खाने के लिए) इसलिए मैं उस पर ध्यान केंद्रित नहीं करूंगा।

इस बारे में एक Google Android बग पोस्ट किया गया है: कृपया इस बग को अभिनीत करके अपना समर्थन जोड़ें (ध्यान दें कि Google ने मुझे "टिप्पणी": बस एक सितारा पर्याप्त है):

http://code.google.com/p/android/issues/detail?id=4441

समाधान का सारांश:

कई पोस्टरों में LayoutInflater.Factory से जुड़े एक हैक का सुझाव दिया गया है। सुझाए गए हैक ने एंड्रॉइड <= 2.2 के लिए काम किया और एंड्रॉइड 2.3 के लिए विफल हो गया क्योंकि हैक ने एक अनिर्धारित धारणा बनाई: कि कोई व्यक्ति लेआउटइनफ्लाटर.फ्लैट () को सीधे उसी लेआउट लेआउट इनफ्लिटर उदाहरण पर कॉल किए बिना LayoutInflater.getView () को कॉल कर सकता है। एंड्रॉइड 2.3 में नए कोड ने इस धारणा को तोड़ दिया और NullPointerException का नेतृत्व किया।

नीचे मेरी थोड़ी परिष्कृत हैक इस धारणा पर भरोसा नहीं करता है।

इसके अलावा, हैक भी एक स्ट्रिंग के रूप में (जावा प्रकार के रूप में नहीं) एक आंतरिक, अनिर्दिष्ट श्रेणी नाम "com.android.internal.view.menu.IconMenuItemView" का उपयोग करने पर भरोसा करते हैं। मुझे इससे बचने का कोई रास्ता नहीं दिख रहा है और फिर भी बताए गए लक्ष्य को पूरा नहीं कर पा रहा हूं। हालांकि, हैक को सावधानीपूर्वक तरीके से करना संभव है जो "com.android.internal.view.menu.IconMenuItemView" वर्तमान सिस्टम पर प्रकट नहीं होता है।

फिर से, समझ लें कि यह एक हैक है और किसी भी तरह से मैं यह दावा नहीं कर रहा हूं कि यह सभी प्लेटफार्मों पर काम करेगा। लेकिन हम डेवलपर्स एक फंतासी अकादमिक दुनिया में नहीं रह रहे हैं, जहां सब कुछ पुस्तक द्वारा होना है: हमें हल करने के लिए एक समस्या है और हमें इसे सबसे अच्छा हल करना होगा जो हम कर सकते हैं। उदाहरण के लिए, यह संभव नहीं लगता है कि "com.android.internal.view.menu.IconMenuItemView" 3.X गोलियों पर मौजूद होगा क्योंकि वे विकल्प मेनू के बजाय एक्शन बार्स का उपयोग करते हैं।

अंत में, कुछ डेवलपर्स ने एंड्रॉइड ऑप्शन्स मेनू को पूरी तरह से दबाकर और अपनी स्वयं की मेनू क्लास (ऊपर कुछ लिंक देखें) लिखकर इस समस्या को हल किया है। मैंने यह कोशिश नहीं की है, लेकिन यदि आपके पास अपना स्वयं का दृश्य लिखने का समय है और यह पता लगाने का तरीका है कि एंड्रॉइड के दृश्य को कैसे बदला जाए (मुझे यकीन है कि शैतान का विवरण यहां है) तो यह एक अच्छा समाधान हो सकता है जिसमें किसी की आवश्यकता नहीं है अघोषित हैक।

हैक:

यहाँ कोड है।

इस कोड का उपयोग करने के लिए, AddOptionsMenuHackerInflaterFactory () ONCE को आपकी गतिविधि से ONCreate () या आपकी गतिविधि onCreateOptionsMenu () पर कॉल करें। यह एक डिफ़ॉल्ट कारखाना सेट करता है जो किसी भी विकल्प मेनू के बाद के निर्माण को प्रभावित करेगा। यह उन विकल्प मेनू को प्रभावित नहीं करता है जो पहले ही बनाए जा चुके हैं (पिछली हैक्स ने सेटमेन्यूबैकग्राउंड () का एक फ़ंक्शन नाम का उपयोग किया था, जो कि बहुत ही भ्रामक है क्योंकि फ़ंक्शन किसी भी मेनू गुणों को वापस करने से पहले सेट नहीं करता है)।

@SuppressWarnings("rawtypes")
static Class       IconMenuItemView_class = null;
@SuppressWarnings("rawtypes")
static Constructor IconMenuItemView_constructor = null;

// standard signature of constructor expected by inflater of all View classes
@SuppressWarnings("rawtypes")
private static final Class[] standard_inflater_constructor_signature = 
new Class[] { Context.class, AttributeSet.class };

protected void addOptionsMenuHackerInflaterFactory()
{
    final LayoutInflater infl = getLayoutInflater();

    infl.setFactory(new Factory()
    {
        public View onCreateView(final String name, 
                                 final Context context,
                                 final AttributeSet attrs)
        {
            if (!name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView"))
                return null; // use normal inflater

            View view = null;

            // "com.android.internal.view.menu.IconMenuItemView" 
            // - is the name of an internal Java class 
            //   - that exists in Android <= 3.2 and possibly beyond
            //   - that may or may not exist in other Android revs
            // - is the class whose instance we want to modify to set background etc.
            // - is the class we want to instantiate with the standard constructor:
            //     IconMenuItemView(context, attrs)
            // - this is what the LayoutInflater does if we return null
            // - unfortunately we cannot just call:
            //     infl.createView(name, null, attrs);
            //   here because on Android 3.2 (and possibly later):
            //   1. createView() can only be called inside inflate(),
            //      because inflate() sets the context parameter ultimately
            //      passed to the IconMenuItemView constructor's first arg,
            //      storing it in a LayoutInflater instance variable.
            //   2. we are inside inflate(),
            //   3. BUT from a different instance of LayoutInflater (not infl)
            //   4. there is no way to get access to the actual instance being used
            // - so we must do what createView() would have done for us
            //
            if (IconMenuItemView_class == null)
            {
                try
                {
                    IconMenuItemView_class = getClassLoader().loadClass(name);
                }
                catch (ClassNotFoundException e)
                {
                    // this OS does not have IconMenuItemView - fail gracefully
                    return null; // hack failed: use normal inflater
                }
            }
            if (IconMenuItemView_class == null)
                return null; // hack failed: use normal inflater

            if (IconMenuItemView_constructor == null)
            {
                try
                {
                    IconMenuItemView_constructor = 
                    IconMenuItemView_class.getConstructor(standard_inflater_constructor_signature);
                }
                catch (SecurityException e)
                {
                    return null; // hack failed: use normal inflater
                }
                catch (NoSuchMethodException e)
                {
                    return null; // hack failed: use normal inflater
                }
            }
            if (IconMenuItemView_constructor == null)
                return null; // hack failed: use normal inflater

            try
            {
                Object[] args = new Object[] { context, attrs };
                view = (View)(IconMenuItemView_constructor.newInstance(args));
            }
            catch (IllegalArgumentException e)
            {
                return null; // hack failed: use normal inflater
            }
            catch (InstantiationException e)
            {
                return null; // hack failed: use normal inflater
            }
            catch (IllegalAccessException e)
            {
                return null; // hack failed: use normal inflater
            }
            catch (InvocationTargetException e)
            {
                return null; // hack failed: use normal inflater
            }
            if (null == view) // in theory handled above, but be safe... 
                return null; // hack failed: use normal inflater


            // apply our own View settings after we get back to runloop
            // - android will overwrite almost any setting we make now
            final View v = view;
            new Handler().post(new Runnable()
            {
                public void run()
                {
                    v.setBackgroundColor(Color.BLACK);

                    try
                    {
                        // in Android <= 3.2, IconMenuItemView implemented with TextView
                        // guard against possible future change in implementation
                        TextView tv = (TextView)v;
                        tv.setTextColor(Color.WHITE);
                    }
                    catch (ClassCastException e)
                    {
                        // hack failed: do not set TextView attributes
                    }
                }
            });

            return view;
        }
    });
}

पढ़ने के लिए धन्यवाद, मजा करें!


15
केवल एक चीज मैं मज़बूती मिलती है, जब यह (और इसी तरह के समाधान) का उपयोग करने की कोशिश कर `है java.lang.IllegalStateException: एक कारखाने पहले से ही इस LayoutInflater` पर सेट किया गया है
Bostone

मेरे लिये कार्य करता है! अंत में एक समाधान के लिए बहुत अच्छा है! जिंजरब्रेड, हनीकॉम्ब और आईसीएस पर परीक्षण किया गया
चाड शुल्त्ज़

सैमसंग गैलेक्सी नेक्सस (4.1.1) और परीक्षण में काम किया! अच्छी चीजें, लुई!
फेलिप कैलदास

2
गैलेक्सी नेक्सस 7 (4.1.1) पर काम करता है, हालांकि पहली बार छिपाए जाने के बाद पाठ का रंग मेनू के हर बाद के कॉल के लिए वापस आ जाता है।
विल क्रु

1
मुझे IllegalStateException भी मिलती है। ऐसा लगता है कि हैक ActionBarSherlock के साथ असंगत है, जिसका मैं उपयोग कर रहा हूं।
ट्रैविस

20

मेनू पृष्ठभूमि के लिए शैली विशेषता है android:panelFullBackground

दस्तावेज़ीकरण क्या कहता है, इसके बावजूद, इसे एक संसाधन (जैसे @android:color/blackया @drawable/my_drawable) होना चाहिए , यदि आप सीधे रंग मान का उपयोग करते हैं तो यह दुर्घटनाग्रस्त हो जाएगा।

यह उन आइटम सीमाओं से भी छुटकारा दिलाएगा, जिन्हें मैं primalpop के समाधान का उपयोग करके बदलने या हटाने में असमर्थ था।

पाठ रंग के रूप में, मुझे 2.2 में शैलियों के माध्यम से इसे सेट करने का कोई तरीका नहीं मिला है और मुझे यकीन है कि मैंने सब कुछ करने की कोशिश की है (जो कि मैंने मेनू पृष्ठभूमि विशेषता की खोज की है)। आपको उसके लिए primalpop के समाधान का उपयोग करने की आवश्यकता होगी।


3
मुझे यह मान कहां सेट करना है? मैं इसे एंड्रॉइड 2.2 पर काम करने के लिए नहीं मिला। या 2.3
Janusz

1
@Janusz Styles.xml में। यह शायद मदद करेगा: developer.android.com/guide/topics/resources/…
Pilot_51

2
काम नहीं करता है, अच्छा है अगर आप यह बता सकते हैं कि यह कहाँ जाना है, तो मेरे मेनू आइटम के लिए एक और शैली बनाने के अलावा हर जगह की कोशिश की .....
जॉन

14

एंड्रॉइड 2.3 के लिए यह कुछ बहुत भारी हैकिंग के साथ किया जा सकता है:

एंड्रॉइड 2.3 के साथ मुद्दों का मूल कारण यह है कि LayoutInflater में mConstructorArgs [0] = mContext केवल रनिंग कॉल के दौरान सेट किया गया है

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/android/view/LayoutInflater.java/#352

protected void setMenuBackground(){

    getLayoutInflater().setFactory( new Factory() {

        @Override
        public View onCreateView (final String name, final Context context, final AttributeSet attrs ) {

            if ( name.equalsIgnoreCase( "com.android.internal.view.menu.IconMenuItemView" ) ) {

                try { // Ask our inflater to create the view
                    final LayoutInflater f = getLayoutInflater();
                    final View[] view = new View[1]:
                    try {
                        view[0] = f.createView( name, null, attrs );
                    } catch (InflateException e) {
                        hackAndroid23(name, attrs, f, view);
                    }
                    // Kind of apply our own background
                    new Handler().post( new Runnable() {
                        public void run () {
                            view.setBackgroundResource( R.drawable.gray_gradient_background);
                        }
                    } );
                    return view;
                }
                catch ( InflateException e ) {
                }
                catch ( ClassNotFoundException e ) {
                }
            }
            return null;
        }
    });
}

static void hackAndroid23(final String name,
    final android.util.AttributeSet attrs, final LayoutInflater f,
    final TextView[] view) {
    // mConstructorArgs[0] is only non-null during a running call to inflate()
    // so we make a call to inflate() and inside that call our dully XmlPullParser get's called
    // and inside that it will work to call "f.createView( name, null, attrs );"!
    try {
        f.inflate(new XmlPullParser() {
            @Override
            public int next() throws XmlPullParserException, IOException {
                try {
                    view[0] = (TextView) f.createView( name, null, attrs );
                } catch (InflateException e) {
                } catch (ClassNotFoundException e) {
                }
                throw new XmlPullParserException("exit");
            }   
        }, null, false);
    } catch (InflateException e1) {
        // "exit" ignored
    }
}

मैंने इसे एंड्रॉइड 2.3 पर काम करने और अभी भी पहले के संस्करणों पर काम करने के लिए परीक्षण किया। यदि बाद के एंड्रॉइड संस्करणों में कुछ भी फिर से टूट जाता है, तो आप इसके बजाय बस डिफ़ॉल्ट मेनू-शैली देखेंगे


यह कोड केवल संस्करण 2.1 तक चलता है। यह कोड यहां बेहतर प्रतीत होता है: stackoverflow.com/questions/2944244/…
फेलिप कैलदास

हाय, मैं अपने कार्य का इस्तेमाल किया है, लेकिन मैं यह निम्न त्रुटि मिला बढ़ा-चढ़ाकर वर्ग com.android.internal.view.menu.IconMenuItemView त्रुटि और उसके बाद एक और अपवाद त्रुटि बढ़ा-चढ़ाकर वर्ग <अज्ञात> ... अब क्या अब मैं क्या करना चाहिए ... ? क्रिप्या मेरि सहायता करे।
रुषभ पटेल

13

बस इस मुद्दे में भी भाग गया, एक ऐप पर जिसे जिंजरब्रेड के साथ संगत होना था और अभी भी होलो-सक्षम उपकरणों से स्टाइल को जितना संभव हो उतना बनाए रखना चाहिए।

मुझे अपेक्षाकृत साफ समाधान मिला, जिसने मेरे लिए ठीक काम किया।

विषय में मैं एक कस्टम पृष्ठभूमि रंग प्राप्त करने के लिए 9-पैच ड्रॉ करने योग्य पृष्ठभूमि का उपयोग करता हूं:

<style name="Theme.Styled" parent="Theme.Sherlock">
   ...
   <item name="android:panelFullBackground">@drawable/menu_hardkey_panel</item>
</style>

मैंने टेक्स्ट कलर को स्टाइल करने की कोशिश करना छोड़ दिया, और कोड में अपने आइटम के लिए टेक्स्ट कलर सेट करने के लिए सिर्फ एक स्पैनबल का इस्तेमाल किया

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getSupportMenuInflater();
   inflater.inflate(R.menu.actions_main, menu);

   if (android.os.Build.VERSION.SDK_INT < 
        android.os.Build.VERSION_CODES.HONEYCOMB) {

        SpannableStringBuilder text = new SpannableStringBuilder();
        text.append(getString(R.string.action_text));
        text.setSpan(new ForegroundColorSpan(Color.WHITE), 
                0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        MenuItem item1 = menu.findItem(R.id.action_item1);
        item1.setTitle(text);
   }

   return true;
}

जिंजरब्रेड डिवाइस पर ActionBarSherlock लाइट विषय का उपयोग करने के साथ मेरे मुद्दे के लिए महान काम करता है! इसके साथ, मैं आसानी से विकल्प मेनू पृष्ठभूमि को हल्के भूरे और पाठ के रंग से काले रंग में बदल सकता हूं (प्रतीक पहले से ही काले रंग के हैं जैसा कि
एक्शनबार में है

12

इस तरह से मैंने मेरा हल किया। मैंने शैलियों में पृष्ठभूमि रंग और पाठ रंग निर्दिष्ट किया है। यानी Res> मान> style.xml फ़ाइल।

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:itemBackground">#ffffff</item>
    <item name="android:textColor">#000000</item>
</style>

1
textcolor हर जगह बदल जाएगा
user3156040

यह सिर्फ आइटम पृष्ठभूमि का रंग बदलता है, और मेनू विकल्प लेआउट में ऊपर और नीचे गद्दी है, यह मदद नहीं करता है
F23

10

एक बात ध्यान दें कि आप लोग बहुत अधिक अन्य पोस्टों की तरह ही इस समस्या को खत्म कर रहे हैं! आपको बस जो कुछ भी पृष्ठभूमि की जरूरत है उसके साथ ड्रॉ करने योग्य चयनकर्ता बनाने की जरूरत है और उन्हें वास्तविक वस्तुओं पर सेट करें। मैं सिर्फ दो घंटे आपके समाधानों की कोशिश कर रहा हूं (सभी इस पृष्ठ पर सुझाए गए हैं) और उनमें से कोई भी काम नहीं किया। यह उल्लेख नहीं करने के लिए कि आपके पास उन प्रयासों / कैच ब्लॉक में अनिवार्य रूप से आपके प्रदर्शन को धीमा कर रहा है जो आपके प्रदर्शन को धीमा करते हैं।

वैसे भी यहाँ एक मेनू xml फ़ाइल है:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/m1"
          android:icon="@drawable/item1_selector"
          />
    <item android:id="@+id/m2"
          android:icon="@drawable/item2_selector"
          />
</menu>

अब आपके item1_selector में:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/item_highlighted" />
    <item android:state_selected="true" android:drawable="@drawable/item_highlighted" />
    <item android:state_focused="true" android:drawable="@drawable/item_nonhighlighted" />
    <item android:drawable="@drawable/item_nonhighlighted" />
</selector>

अगली बार जब आप सुपरमार्केट के माध्यम से कनाडा जाने का फैसला करते हैं तो Google मानचित्र आज़माएं!


मैं पूरी तरह सहमत हूँ। एंड्रॉइड को फिर से क्यों मजबूत करें जब वह =) पहले से मौजूद है?
फ्रेड्रिक

बहुत अच्छा काम करता है। अपने आइकन और वांछित पृष्ठभूमि के साथ एक लेयरबल ड्रा करने योग्य बनाएं। एकमात्र समस्या यह है कि मुझे पता नहीं है कि क्या मैं टेक्स्ट का रंग बदल सकता हूं। इसलिए हर पृष्ठभूमि का रंग काम नहीं करता
Janusz

52
सुंदर, सुरुचिपूर्ण, और पूरी तरह से इस मुद्दे को संबोधित नहीं करता है।
एईए

1
अगर मैं गलत नहीं हूं, तो यह सिर्फ आइकन के लिए पृष्ठभूमि को बदलता है, न कि मेनू आइटम को ही, जो सफेद रहता है।
Jrom

3
यह सवाल का पहलू नहीं है। यह कुल मिलाकर अलग सोच है।
कोस्टाडिन


3
    /* 
     *The Options Menu (the one that pops up on pressing the menu button on the emulator) 
     * can be customized to change the background of the menu 
     *@primalpop  
   */ 

    package com.pop.menu;

    import android.app.Activity;
    import android.content.Context;
    import android.os.Bundle;
    import android.os.Handler;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.InflateException;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.View;
    import android.view.LayoutInflater.Factory;

    public class Options_Menu extends Activity {

        private static final String TAG = "DEBUG";

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

        }

        /* Invoked when the menu button is pressed */

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // TODO Auto-generated method stub
            super.onCreateOptionsMenu(menu);
            MenuInflater inflater = new MenuInflater(getApplicationContext());
            inflater.inflate(R.menu.options_menu, menu);
            setMenuBackground();
            return true;
        }

        /*IconMenuItemView is the class that creates and controls the options menu 
         * which is derived from basic View class. So We can use a LayoutInflater 
         * object to create a view and apply the background.
         */
        protected void setMenuBackground(){

            Log.d(TAG, "Enterting setMenuBackGround");
            getLayoutInflater().setFactory( new Factory() {

                @Override
                public View onCreateView ( String name, Context context, AttributeSet attrs ) {

                    if ( name.equalsIgnoreCase( "com.android.internal.view.menu.IconMenuItemView" ) ) {

                        try { // Ask our inflater to create the view
                            LayoutInflater f = getLayoutInflater();
                            final View view = f.createView( name, null, attrs );
                            /* 
                             * The background gets refreshed each time a new item is added the options menu. 
                             * So each time Android applies the default background we need to set our own 
                             * background. This is done using a thread giving the background change as runnable
                             * object
                             */
                            new Handler().post( new Runnable() {
                                public void run () {
                                    view.setBackgroundResource( R.drawable.background);
                                }
                            } );
                            return view;
                        }
                        catch ( InflateException e ) {}
                        catch ( ClassNotFoundException e ) {}
                    }
                    return null;
                }
            });
        }
    }

3
कृपया ऐसा न करें: name.equalsIgnoreCase ("com.android.internal.view.menu.IconMenuItemView" जैसा कि नाम स्पष्ट रूप से इंगित करता है, यह निजी कार्यान्वयन विवरण का उपयोग कर रहा है, और इस प्रकार किसी भी अपडेट या डिवाइस को तोड़ सकता है
हैकबॉड

1
IconMenuItemView वह वर्ग है जो विकल्प मेनू बनाता है और नियंत्रित करता है जो मूल व्यू वर्ग से लिया गया है। यह वर्ग एंड्रॉइड सोर्स कोड से है और कम से कम एपीआई संस्करण 5 के बाद से मौजूद है। मैं इसे किसी भी प्लेटफॉर्म अपडेट या डिवाइस पर ब्रेकिंग नहीं देख सकता।
प्रिमल पपचन

1
आप इसे देख नहीं सकते क्योंकि आप भविष्य नहीं देख सकते। यहां तक ​​कि अगर कोई निश्चित तरीका था, तो यह बुरा है
एचएक्सकैन

धन्यवाद, यह एक चुटकी में उपयोगी है। हालाँकि, विशेष मामलों में काम नहीं करता है, जैसे, onCreateOptionsMenu में बनाए गए आइटम, लेकिन onPrepareOptionsMenu में अक्षम, लेकिन बाद में फिर से सक्षम किया गया।
एचआरजे

3

धन्यवाद माक्र्स! यह कुछ सिंटैक्स त्रुटियों को ठीक करके 2.3 पर काम करता है, यहां निश्चित कोड है

    protected void setMenuBackground() {
    getLayoutInflater().setFactory(new Factory() {

        @Override
        public View onCreateView(final String name, final Context context,
                final AttributeSet attrs) {

            if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {

                try { // Ask our inflater to create the view
                    final LayoutInflater f = getLayoutInflater();
                    final View[] view = new View[1];
                    try {
                        view[0] = f.createView(name, null, attrs);
                    } catch (InflateException e) {
                        hackAndroid23(name, attrs, f, view);
                    }
                    // Kind of apply our own background
                    new Handler().post(new Runnable() {
                        public void run() {
                            view[0].setBackgroundColor(Color.WHITE);

                        }
                    });
                    return view[0];
                } catch (InflateException e) {
                } catch (ClassNotFoundException e) {

                }
            }
            return null;
        }
    });
}

static void hackAndroid23(final String name,
        final android.util.AttributeSet attrs, final LayoutInflater f,
        final View[] view) {
    // mConstructorArgs[0] is only non-null during a running call to
    // inflate()
    // so we make a call to inflate() and inside that call our dully
    // XmlPullParser get's called
    // and inside that it will work to call
    // "f.createView( name, null, attrs );"!
    try {
        f.inflate(new XmlPullParser() {
            @Override
            public int next() throws XmlPullParserException, IOException {
                try {
                    view[0] = (TextView) f.createView(name, null, attrs);
                } catch (InflateException e) {
                } catch (ClassNotFoundException e) {
                }
                throw new XmlPullParserException("exit");
            }
        }, null, false);
    } catch (InflateException e1) {
        // "exit" ignored
    }
}

1
मैं इस के लिए मिलती है: java.lang.IllegalStateException: एक कारखाने पहले से ही इस LayoutInflater पर सेट किया गया है
Bostone

ActionBarSherlock और संगतता ढांचे के साथ काम करने के लिए और IllegalStateException से बचने के लिए यह ट्रिक stackoverflow.com/questions/13415284/…
avianey

3
protected void setMenuBackground() {
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView (String name, Context context, AttributeSet attrs) {
            if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
                try {
                    // Ask our inflater to create the view
                    LayoutInflater f = getLayoutInflater();
                    final View view = f.createView(name, null, attrs);
                    // Kind of apply our own background
                    new Handler().post( new Runnable() {
                        public void run () {
                            view.setBackgroundResource(R.drawable.gray_gradient_background);
                        }
                    });
                    return view;
                }
                catch (InflateException e) {
                }
                catch (ClassNotFoundException e) {
                }
            }
            return null;
        }
    });
}

यह XML फ़ाइल है

gradient 
    android:startColor="#AFAFAF" 
    android:endColor="#000000"
    android:angle="270"
shape

1

यदि आप एक मनमाना रंग सेट करना चाहते हैं, तो यह काम के लिए अच्छा लगता है androidx। किटकैट और पाई पर परीक्षण किया गया। इसे अपने में रखें AppCompatActivity:

@Override public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
    if (name.equals("androidx.appcompat.view.menu.ListMenuItemView") &&
            parent.getParent() instanceof FrameLayout) {
            ((View) parent.getParent()).setBackgroundColor(yourFancyColor);
    }
    return super.onCreateView(parent, name, context, attrs);
}

यह रंग सेट करता है android.widget.PopupWindow$PopupBackgroundView, जो, जैसा कि आपने अनुमान लगाया होगा, पृष्ठभूमि रंग खींचता है। कोई अतिदेय नहीं है और आप अर्ध-पारदर्शी रंगों का भी उपयोग कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.