옵션 메뉴의 배경색을 변경하는 방법은 무엇입니까?


96

흰색 인 옵션 메뉴의 기본 색상을 변경하려고합니다. 옵션 메뉴의 모든 항목에 검정색 배경이 필요합니다.

메뉴 요소 내의 항목 요소에서 android : itemBackground = "# 000000"과 같은 촬영을 시도했지만 작동하지 않았습니다.

어떻게 할 수 있습니까?



답변:


65

모든 옵션을 시도하는 데 상당한 시간을 보낸 후 AppCompat v7을 사용하여 앱을 가져와 오버플로 메뉴 배경을 변경할 수있는 유일한 방법은 itemBackground 속성을 사용하는 것입니다.

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

API 4.2에서 5.0으로 테스트되었습니다.


2
이것은 쉽고 간단하게 받아 들여진 대답이어야합니다.
Alex Ardavin 2016

3
그러나 이것은 파급 효과를 제거합니다 : / 어쨌든 그것을 다시 넣으려면?
David Velasquez

별도의 항목 배경이 아닌 전체 창 배경을 변경하고 싶습니다. 예를 들어 이러한 배경 (테두리 포함)을 설정하면 각 항목에 테두리가 추가됩니다 ...
user25

1
메뉴 텍스트 색상은 어떻습니까?
doctorram

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 태블릿에서 아무 일도하지 않습니다.

문제 설명 (부정적인 의견으로 트리거 응답하기 전에이 내용을 읽으십시오) :

옵션 메뉴는 장치마다 매우 다른 스타일을 가지고 있습니다. 일부에는 흰색 텍스트가있는 순수한 검정색, 일부에는 검은 색 텍스트가있는 순수한 흰색. 나와 다른 많은 개발자가 옵션 메뉴 셀 의 배경색과 옵션 메뉴 텍스트의 색상 을 제어하려고 합니다. .

특정 앱 개발자는 셀 배경색 (텍스트 색상이 아님) 만 설정하면되며 다른 답변에 설명 된 android : panelFullBackground 스타일을 사용하여 더 깔끔한 방식으로이를 수행 할 수 있습니다. 그러나 현재 스타일을 사용하여 옵션 메뉴 텍스트 색상을 제어 할 수있는 방법이 없으므로이 방법을 사용하여 텍스트가 "사라지지 않는"다른 색상으로 배경을 변경할 수 있습니다.

문서화 된 미래 보장형 솔루션을 사용하여이를 수행하고 싶지만 Android <= 2.3부터는 사용할 수 없습니다. 따라서 현재 버전에서 작동하고 향후 버전에서 충돌 / 중단 될 가능성을 최소화하도록 설계된 솔루션을 사용해야합니다. 우리는 실패해야 할 경우 기본 동작으로 정상적으로 실패하는 솔루션을 원합니다.

옵션 메뉴 (일반적으로 나머지 앱의 시각적 스타일과 일치시키기 위해)의 모양을 제어해야하는 합법적 인 이유가 많이 있으므로 이에 대해서는 다루지 않겠습니다.

이에 대해 게시 된 Google Android 버그가 있습니다.이 버그에 별표를 표시하여 지원을 추가하십시오 (Google은 "나도"댓글을 권장하지 않습니다. 별표 하나만으로도 충분합니다).

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

솔루션 요약 :

여러 포스터에서 LayoutInflater.Factory와 관련된 해킹을 제안했습니다. 제안 된 해킹은 Android <= 2.2에서 작동했으며 Android 2.3에서는 실패했습니다. 해킹이 문서화되지 않은 가정을 만들었 기 때문입니다. 현재 동일한 LayoutInflater 인스턴스에서 LayoutInflater.inflate ()를 호출하지 않고 LayoutInflater.getView ()를 직접 호출 할 수 있다는 가정입니다. Android 2.3의 새 코드는이 가정을 어 기고 NullPointerException을 발생 시켰습니다.

아래의 약간 세련된 해킹은이 가정에 의존하지 않습니다.

또한 해킹은 문서화되지 않은 내부 클래스 이름 "com.android.internal.view.menu.IconMenuItemView"를 문자열 (Java 유형이 아님)로 사용하는데도 의존합니다. 나는 이것을 피하고 여전히 명시된 목표를 달성 할 방법을 보지 못합니다. 그러나 현재 시스템에 "com.android.internal.view.menu.IconMenuItemView"가 나타나지 않으면 폴백되는 신중한 방법으로 해킹을 할 수 있습니다.

다시 말하지만 이것이 해킹이라는 것을 이해하고 이것이 모든 플랫폼에서 작동한다고 주장하는 것은 아닙니다. 그러나 우리 개발자들은 모든 것이 책에 의해 이루어져야하는 환상의 학문 세계에 살고 있지 않습니다. 우리는 해결해야 할 문제가 있고 가능한 한 최선을 다해 해결해야합니다. 예를 들어 3.X 태블릿에는 옵션 메뉴 대신 작업 표시 줄을 사용하기 때문에 "com.android.internal.view.menu.IconMenuItemView"가 존재하지 않을 것 같습니다.

마지막으로 일부 개발자는 Android 옵션 메뉴를 완전히 억제하고 자체 메뉴 클래스를 작성하여이 문제를 해결했습니다 (위의 일부 링크 참조). 나는 이것을 시도하지 않았지만 자신의 뷰를 작성하고 Android의 뷰를 대체하는 방법을 알아낼 시간이 있다면 (여기에 악마가 있다고 확신합니다) 필요하지 않은 멋진 솔루션이 될 수 있습니다 문서화되지 않은 해킹.

마구 자르기:

다음은 코드입니다.

이 코드를 사용하려면 활동 onCreate () 또는 활동 onCreateOptionsMenu ()에서 addOptionsMenuHackerInflaterFactory ()를 한 번 호출하십시오. 옵션 메뉴의 후속 생성에 영향을 미치는 기본 공장을 설정합니다. 이미 생성 된 옵션 메뉴에는 영향을주지 않습니다 (이전 해킹은 setMenuBackground () 함수 이름을 사용했습니다. 함수가 반환되기 전에 메뉴 속성을 설정하지 않았기 때문에 매우 오해의 소지가 있습니다).

@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

나를 위해 작동합니다! 마침내 해결책을 갖게되어 정말 좋습니다! Gingerbread, Honeycomb 및 ICS에서 테스트
Chad Schultz

Samsung Galaxy Nexus (4.1.1)에서 테스트되었으며 작동 중입니다! 좋은 물건, 루이스!
Felipe Caldas

2
Galaxy Nexus 7 (4.1.1)에서 작동하지만 처음 숨긴 후 메뉴를 호출 할 때마다 텍스트 색상이 되돌아갑니다.
Will Kru

1
IllegalStateException도 발생합니다. 해킹이 내가 사용중인 ActionBarSherlock과 호환되지 않는 것 같습니다.
Travis

20

메뉴 배경의 스타일 속성은 android:panelFullBackground입니다.

문서에 나와있는 내용에도 불구하고 리소스 (예 : @android:color/black또는 @drawable/my_drawable) 여야 하지만 색상 값을 직접 사용하면 충돌이 발생합니다.

이렇게하면 primalpop의 솔루션을 사용하여 변경하거나 제거 할 수 없었던 항목 테두리도 제거됩니다.

텍스트 색상에 관해서는 2.2에서 스타일을 통해 설정하는 방법을 찾지 못했고 모든 것을 시도했음을 확신합니다 (메뉴 배경 속성을 발견 한 방법). 이를 위해 primalpop의 솔루션을 사용해야합니다.


3
이 값을 어디에 설정해야합니까? Android 2.2에서 작동하지 못했습니다. 또는 2.3
Janusz 2011 년

1
@Janusz In Styles.xml. 이것은 아마도 도움이 될 것입니다 : developer.android.com/guide/topics/resources/…
Pilot_51 2011 년

2
작동하지 않습니다. 어디로 가야하는지 명시 할 수 있으면 좋습니다. 내 메뉴 항목에 속성을 부여 할 다른 스타일을 만드는 것을 제외하고 모든 곳에서 시도해 보았습니다 .....
John

14

Android 2.3의 경우 매우 무거운 해킹으로 수행 할 수 있습니다.

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

Android 2.3에서 작동하고 이전 버전에서도 작동하도록 테스트했습니다. 이후 Android 버전에서 문제가 다시 발생하면 대신 기본 메뉴 스타일이 표시됩니다.


이 코드는 버전 2.1까지만 실행됩니다.이 코드는 더 나은 것 같습니다 : stackoverflow.com/questions/2944244/…
Felipe Caldas

안녕하세요, 귀하의 기능을 사용했지만 다음 오류 오류 가 발생했습니다 .com.android.internal.view.menu.IconMenuItemView 클래스를 팽창 한 다음 예외 오류가 하나 더 발생했습니다. <unknown> ... 이제 어떻게해야합니까? ? 제발 도와주세요.
Rushabh Patel 2012 년

13

Gingerbread와 호환되어야하고 Holo 지원 장치의 스타일을 가능한 한 많이 유지해야하는 앱에서도이 문제가 발생했습니다.

나는 비교적 깨끗한 솔루션을 찾았으며 저에게 적합했습니다.

테마에서는 9 패치 드로어 블 배경을 사용하여 사용자 정의 배경색을 얻습니다.

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

텍스트 색상 스타일을 포기하고 Spannable을 사용하여 코드에서 내 항목의 텍스트 색상을 설정했습니다.

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

Gingerbread 장치에서 ActionBarSherlock Light 테마를 사용할 때 내 문제에 잘 맞습니다! 이렇게하면 옵션 메뉴 배경을 밝은 회색으로, 텍스트 색상을 검은 색으로 쉽게 변경할 수 있습니다 (아이콘은 ActionBar에서와 같이 이미 검은 색입니다! 감사합니다!
florianbaethge 2013

13

이것이 내가 내 문제를 해결 한 방법입니다. 스타일에서 배경색과 텍스트 색상을 지정했습니다. ie res> values> styles.xml 파일.

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

1
텍스트 색상은 사방 바꿀 것
user3156040

항목 배경색 만 변경하고 메뉴 옵션 레이아웃에는 상단 및 하단 패딩이 있지만 도움이되지 않습니다.
FarshidABZ

10

여러분이 다른 많은 게시물과 마찬가지로 문제를 지나치게 복잡하게 만들고 있다는 점에 유의해야합니다! 필요한 모든 배경으로 드로어 블 선택기를 만들고 실제 항목으로 설정하기 만하면됩니다. 솔루션을 시도하는 데 두 시간을 소비했지만 (이 페이지에서 모두 제 안됨) 어느 것도 작동하지 않았습니다. 당신이 가지고있는 try / catch 블록에서 본질적으로 성능을 저하시키는 수많은 오류가 있다는 것은 말할 것도 없습니다.

어쨌든 여기에 메뉴 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지도를 사용해보세요!


전적으로 동의합니다. 그가 =) 이미 존재하는데 왜 안드로이드를 재창조할까요?
Fredrik

잘 작동합니다. 아이콘과 원하는 배경으로 레이어 목록 드로어 블을 만듭니다. 유일한 문제는 텍스트 색상을 변경할 수 있는지 모르겠다는 것입니다. 따라서 모든 배경색이 작동하는 것은 아닙니다
Janusz 2011-06-28

52
아름답고 우아하며 완전히 문제를 해결하지 못합니다.
Aea 2011

1
내가 착각하지 않았다면 이것은 메뉴 항목 자체가 아닌 아이콘의 배경을 변경하는 것뿐입니다.
Jrom

3
이것은 의문의 여지가 없습니다. 이것은 완전히 다른 생각입니다.
Kostadin 2012

4
 <style name="AppThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:itemBackground">#000000</item>
</style>

이것은 나를 위해 잘 작동합니다


제목 색상 변경하는 방법
베즈 라피

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"이름에서 알 수 있듯이 이것은 비공개 구현 세부 정보를 사용하고 있으므로 모든 플랫폼 업데이트 또는 기기에서 중단 될 수 있습니다.
hackbod

1
IconMenuItemView는 기본 View 클래스에서 파생 된 옵션 메뉴를 생성하고 제어하는 ​​클래스입니다. 이 클래스는 Android 소스 코드에서 가져 왔으며 최소한 api 버전 5부터 존재했습니다. 플랫폼 업데이트 나 장치에서 중단되는 것을 볼 수 없습니다.
Primal Pappachan

1
미래를 볼 수 없기 때문에 볼 수 없습니다. 확신 할 수있는 방법이 있어도 나쁜 습관입니다
HXCaine

고마워, 이것은 핀치에 유용합니다. 그러나 onCreateOptionsMenu에서 만든 항목과 같은 특수한 경우에는 작동하지 않지만 onPrepareOptionsMenu에서는 비활성화되었다가 나중에 다시 활성화됩니다.
HRJ 2011 년

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. KitKat 및 Pie에서 테스트되었습니다. 이것을 당신의 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당신이 짐작했듯이 배경색을 그리는의 색상을 설정합니다. 오버 드로우가 없으며 반투명 색상도 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.