ฉันสามารถเปลี่ยนสีพื้นหลังของรายการเมนูใน Android ได้หรือไม่
โปรดแจ้งให้เราทราบหากใครมีวิธีแก้ไขปัญหานี้ ตัวเลือกสุดท้ายจะเห็นได้ชัดว่ากำหนดเอง แต่จะมีวิธีใดในการเปลี่ยนสีข้อความโดยไม่ต้องกำหนดเอง
ฉันสามารถเปลี่ยนสีพื้นหลังของรายการเมนูใน Android ได้หรือไม่
โปรดแจ้งให้เราทราบหากใครมีวิธีแก้ไขปัญหานี้ ตัวเลือกสุดท้ายจะเห็นได้ชัดว่ากำหนดเอง แต่จะมีวิธีใดในการเปลี่ยนสีข้อความโดยไม่ต้องกำหนดเอง
คำตอบ:
บรรทัดเดียวในธีมของคุณ :)
<item name="android:actionMenuTextColor">@color/your_color</item>
actionBarStyle
ตัวอย่างเช่น มันจะไม่ทำงานภายในactionBarStyle
แม้ว่ามันจะดูสมเหตุสมผลก็ตาม!
<item name="actionMenuTextColor">@color/your_color</item>
อย่าใช้เนมสเปซ Android
theme
ดูเหมือนว่า
<item name="android:itemTextAppearance">@style/myCustomMenuTextAppearance</item>
ในรูปแบบของฉันและ
<style name="myCustomMenuTextAppearance" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
<item name="android:textColor">@android:color/primary_text_dark</item>
</style>
in styles.xml เปลี่ยนลักษณะของ list-items แต่ไม่ใช่รายการเมนู
android:itemTextAppearance
แอตทริบิวต์ไม่สามารถวางไว้ในรูปแบบที่มีผู้ปกครองparent="@android:style/Widget.Holo.ListPopupWindow"
มาตั้งแต่ปีที่จะไม่ทำให้ถูกต้อง android:Theme.Holo.Light.DarkActionBar
มันจะต้องเป็นในสไตล์ระดับบนสุดอย่างหนึ่งที่มีผู้ปกครอง
Theme.Holo
หรือTheme.Holo.Light.DarkActionBar
หรือคล้ายกัน
คุณสามารถเปลี่ยนสีของMenuItem
ข้อความได้อย่างง่ายดายโดยใช้แทนSpannableString
String
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.your_menu, menu);
int positionOfMenuItem = 0; // or whatever...
MenuItem item = menu.getItem(positionOfMenuItem);
SpannableString s = new SpannableString("My red MenuItem");
s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
item.setTitle(s);
}
menu.findItem(R.id.menu_item_id);
แทนmenu.getItem()
หากคุณใช้ Toolbar ใหม่ด้วยธีมTheme.AppCompat.Light.NoActionBar
คุณสามารถจัดรูปแบบได้ตามวิธีต่อไปนี้
<style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:textColorPrimary">@color/my_color1</item>
<item name="android:textColorSecondary">@color/my_color2</item>
<item name="android:textColor">@color/my_color3</item>
</style>`
ตามผลลัพธ์ที่ฉันได้รับ
android:textColorPrimary
คือสีข้อความที่แสดงชื่อกิจกรรมของคุณซึ่งเป็นข้อความหลักของแถบเครื่องมือ
android:textColorSecondary
เป็นสีข้อความสำหรับปุ่มคำบรรยายและตัวเลือกเพิ่มเติม (3 จุด) (ใช่มันเปลี่ยนสีตามคุณสมบัตินี้!)
android:textColor
เป็นสีสำหรับข้อความอื่นทั้งหมดรวมถึงเมนู
ในที่สุดตั้งค่าชุดรูปแบบเป็นแถบเครื่องมือ
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:theme="@style/ToolbarTheme"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"/>
android:actionMenuTextColor
(ดูstackoverflow.com/a/5538709/423105 )
หากคุณใช้เมนู<android.support.design.widget.NavigationView />
จากนั้นเพิ่มบรรทัดด้านล่างในNavigationView
:
app:itemTextColor="your color"
นอกจากนี้ยังมี colorTint สำหรับไอคอนมันจะแทนที่สีสำหรับไอคอนของคุณเช่นกัน เพื่อที่คุณจะต้องเพิ่มบรรทัดด้านล่าง:
app:itemIconTint="your color"
ตัวอย่าง:
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:itemTextColor="@color/color_white"
app:itemIconTint="@color/color_white"
android:background="@color/colorPrimary"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer"/>
หวังว่ามันจะช่วยคุณ
ฉันไปเกี่ยวกับมันโดยทางโปรแกรมเช่นนี้:
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.changeip_card_menu, menu);
for(int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
SpannableString spanString = new SpannableString(menu.getItem(i).getTitle().toString());
spanString.setSpan(new ForegroundColorSpan(Color.BLACK), 0, spanString.length(), 0); //fix the color to white
item.setTitle(spanString);
}
return true;
}
อย่างที่คุณเห็นในคำถามนี้คุณควร:
<item name="android:textColorPrimary">yourColor</item>
โค้ดด้านบนเปลี่ยนสีข้อความของรายการแอ็คชันเมนูสำหรับ API> = v21
<item name="actionMenuTextColor">@android:color/holo_green_light</item>
ด้านบนเป็นรหัสสำหรับ API <v21
ฉันใช้แท็ก html เพื่อเปลี่ยนสีข้อความของรายการเดียวเมื่อรายการเมนูขยายเกินจริง หวังว่ามันจะเป็นประโยชน์
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);
menu.findItem(R.id.main_settings).setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
return true;
}
วิธีที่ง่ายที่สุดในการสร้างสีเมนูที่กำหนดเองสำหรับแถบเครื่องมือเดียวไม่ใช่สำหรับ AppTheme
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay.MenuBlue">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
</android.support.design.widget.AppBarLayout>
แถบเครื่องมือปกติบน styles.xml
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
สไตล์แถบเครื่องมือที่กำหนดเองของเรา
<style name="AppTheme.AppBarOverlay.MenuBlue">
<item name="actionMenuTextColor">@color/blue</item>
</style>
ใน Kotlin ฉันเขียนส่วนขยายเหล่านี้:
fun MenuItem.setTitleColor(color: Int) {
val hexColor = Integer.toHexString(color).toUpperCase().substring(2)
val html = "<font color='#$hexColor'>$title</font>"
this.title = html.parseAsHtml()
}
@Suppress("DEPRECATION")
fun String.parseAsHtml(): Spanned {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
} else {
Html.fromHtml(this)
}
}
และใช้ดังนี้:
menu.findItem(R.id.main_settings).setTitleColor(Color.RED)
คำตอบสั้น ๆ คือใช่ โชคดีนะคุณ!
หากต้องการทำเช่นนั้นคุณจะต้องแทนที่สไตล์บางอย่างของสไตล์เริ่มต้นของ Android:
ก่อนอื่นให้ดูคำจำกัดความของธีมใน Android:
<style name="Theme.IconMenu">
<!-- Menu/item attributes -->
<item name="android:itemTextAppearance">@android:style/TextAppearance.Widget.IconMenu.Item</item>
<item name="android:itemBackground">@android:drawable/menu_selector</item>
<item name="android:itemIconDisabledAlpha">?android:attr/disabledAlpha</item>
<item name="android:horizontalDivider">@android:drawable/divider_horizontal_bright</item>
<item name="android:verticalDivider">@android:drawable/divider_vertical_bright</item>
<item name="android:windowAnimationStyle">@android:style/Animation.OptionsPanel</item>
<item name="android:moreIcon">@android:drawable/ic_menu_more</item>
<item name="android:background">@null</item>
</style>
ดังนั้นการปรากฏตัวของข้อความในเมนูอยู่ใน@android:style/TextAppearance.Widget.IconMenu.Item
ตอนนี้ในการกำหนดรูปแบบ :
<style name="TextAppearance.Widget.IconMenu.Item" parent="TextAppearance.Small">
<item name="android:textColor">?textColorPrimaryInverse</item>
</style>
ดังนั้นตอนนี้เรามีชื่อของสีที่เป็นปัญหาถ้าคุณดูในโฟลเดอร์สีของทรัพยากรของระบบ:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled" />
<item android:state_window_focused="false" android:color="@android:color/bright_foreground_light" />
<item android:state_pressed="true" android:color="@android:color/bright_foreground_light" />
<item android:state_selected="true" android:color="@android:color/bright_foreground_light" />
<item android:color="@android:color/bright_foreground_light" />
<!-- not selected -->
</selector>
ในที่สุดนี่คือสิ่งที่คุณต้องทำ:
แทนที่ "TextAppearance.Widget.IconMenu.Item" และสร้างสไตล์ของคุณเอง จากนั้นลิงก์ไปยังตัวเลือกของคุณเองเพื่อให้เป็นแบบที่คุณต้องการ หวังว่านี่จะช่วยคุณได้ โชคดี!
เมนูตัวเลือกใน android สามารถปรับแต่งเพื่อตั้งค่าพื้นหลังหรือเปลี่ยนลักษณะข้อความ ไม่สามารถเปลี่ยนพื้นหลังและสีข้อความในเมนูโดยใช้ธีมและสไตล์ ซอร์สโค้ด Android (data \ res \ layout \ icon_menu_item_layout.xml) ใช้รายการที่กำหนดเองของคลาส“ com.android.internal.view.menu.IconMenuItem” ดูสำหรับโครงร่างเมนู เราสามารถทำการเปลี่ยนแปลงในคลาสข้างต้นเพื่อปรับแต่งเมนู เพื่อให้บรรลุเดียวกันใช้ LayoutInflater ระดับโรงงานและตั้งค่าพื้นหลังและสีข้อความสำหรับมุมมอง
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my_menu, menu);
getLayoutInflater().setFactory(new Factory() {
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (name .equalsIgnoreCase(“com.android.internal.view.menu.IconMenuItemView”)) {
try{
LayoutInflater f = getLayoutInflater();
final View view = f.createView(name, null, attrs);
new Handler().post(new Runnable() {
public void run() {
// set the background drawable
view .setBackgroundResource(R.drawable.my_ac_menu_background);
// set the text color
((TextView) view).setTextColor(Color.WHITE);
}
});
return view;
} catch (InflateException e) {
} catch (ClassNotFoundException e) {}
}
return null;
}
});
return super.onCreateOptionsMenu(menu);
}
03-23 19:45:25.134: E/AndroidRuntime(26761): java.lang.IllegalStateException: A factory has already been set on this LayoutInflater
ขอบคุณสำหรับตัวอย่างโค้ด ฉันต้องแก้ไขมันไปให้มันใช้งานได้กับเมนูบริบท นี่คือทางออกของฉัน
static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};
class MenuColorFix implements LayoutInflater.Factory {
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (name.equalsIgnoreCase("com.android.internal.view.menu.ListMenuItemView")) {
try {
Class<? extends ViewGroup> clazz = context.getClassLoader().loadClass(name).asSubclass(ViewGroup.class);
Constructor<? extends ViewGroup> constructor = clazz.getConstructor(constructorSignature);
final ViewGroup view = constructor.newInstance(new Object[]{context,attrs});
new Handler().post(new Runnable() {
public void run() {
try {
view.setBackgroundColor(Color.BLACK);
List<View> children = getAllChildren(view);
for(int i = 0; i< children.size(); i++) {
View child = children.get(i);
if ( child instanceof TextView ) {
((TextView)child).setTextColor(Color.WHITE);
}
}
}
catch (Exception e) {
Log.i(TAG, "Caught Exception!",e);
}
}
});
return view;
}
catch (Exception e) {
Log.i(TAG, "Caught Exception!",e);
}
}
return null;
}
}
public List<View> getAllChildren(ViewGroup vg) {
ArrayList<View> result = new ArrayList<View>();
for ( int i = 0; i < vg.getChildCount(); i++ ) {
View child = vg.getChildAt(i);
if ( child instanceof ViewGroup) {
result.addAll(getAllChildren((ViewGroup)child));
}
else {
result.add(child);
}
}
return result;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
LayoutInflater lInflater = getLayoutInflater();
if ( lInflater.getFactory() == null ) {
lInflater.setFactory(new MenuColorFix());
}
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.myMenu, menu);
}
สำหรับฉันมันใช้งานได้กับ Android 1.6, 2.03 และ 4.03
ฉันพบมันยูเรก้า !!
ในธีมแอพของคุณ:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/ActionBarTheme</item>
<!-- backward compatibility -->
<item name="actionBarStyle">@style/ActionBarTheme</item>
</style>
นี่คือชุดรูปแบบแถบการกระทำของคุณ:
<style name="ActionBarTheme" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">@color/actionbar_bg_color</item>
<item name="popupTheme">@style/ActionBarPopupTheme</item
<!-- backward compatibility -->
<item name="background">@color/actionbar_bg_color</item>
</style>
และนี่คือธีมป๊อปอัพของคุณ:
<style name="ActionBarPopupTheme">
<item name="android:textColor">@color/menu_text_color</item>
<item name="android:background">@color/menu_bg_color</item>
</style>
ไชโย;)
เพื่อเปลี่ยนสีข้อความของรายการเมนูใช้รหัสด้านล่าง
<style name="AppToolbar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:itemTextAppearance">@style/menu_item_color</item>
</style>
ที่ไหน
<style name="menu_item_color">
<item name="android:textColor">@color/app_font_color</item>
</style>
ขอบคุณ max.musterman นี่เป็นวิธีแก้ปัญหาที่ฉันได้ทำงานในระดับ 22:
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(this);
setMenuTextColor(menu, R.id.displaySummary, R.string.show_summary);
setMenuTextColor(menu, R.id.about, R.string.text_about);
setMenuTextColor(menu, R.id.importExport, R.string.import_export);
setMenuTextColor(menu, R.id.preferences, R.string.settings);
return true;
}
private void setMenuTextColor(Menu menu, int menuResource, int menuTextResource) {
MenuItem item = menu.findItem(menuResource);
SpannableString s = new SpannableString(getString(menuTextResource));
s.setSpan(new ForegroundColorSpan(Color.BLACK), 0, s.length(), 0);
item.setTitle(s);
}
hardcoded Color.BLACK
อาจกลายเป็นพารามิเตอร์เพิ่มเติมสำหรับsetMenuTextColor
วิธีการ android:showAsAction="never"
นอกจากนี้ผมใช้เพียงแค่นี้สำหรับรายการเมนูที่มี
คุณสามารถตั้งค่าสีโดยทางโปรแกรม
private static void setMenuTextColor(final Context context, final Toolbar toolbar, final int menuResId, final int colorRes) {
toolbar.post(new Runnable() {
@Override
public void run() {
View settingsMenuItem = toolbar.findViewById(menuResId);
if (settingsMenuItem instanceof TextView) {
if (DEBUG) {
Log.i(TAG, "setMenuTextColor textview");
}
TextView tv = (TextView) settingsMenuItem;
tv.setTextColor(ContextCompat.getColor(context, colorRes));
} else { // you can ignore this branch, because usually there is not the situation
Menu menu = toolbar.getMenu();
MenuItem item = menu.findItem(menuResId);
SpannableString s = new SpannableString(item.getTitle());
s.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, colorRes)), 0, s.length(), 0);
item.setTitle(s);
}
}
});
}
การเพิ่มสิ่งนี้ลงในสไตล์ของฉัน
<item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
เพียงเพิ่มสิ่งนี้ลงในธีมของคุณ
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:itemTextAppearance">@style/AppTheme.ItemTextStyle</item>
</style>
<style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
<item name="android:textColor">@color/orange_500</item>
</style>
ทดสอบกับ API 21
<style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget">
มิฉะนั้นข้อความจะปรากฏเล็กเกินไปในเมนูโอเวอร์โฟลว์ โปรดทราบว่าเทคนิคนี้ใช้งานได้กับ Android 5 ขึ้นไปเท่านั้น
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.search, menu);
MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
SearchView searchView = (SearchView) myActionMenuItem.getActionView();
EditText searchEditText = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchEditText.setTextColor(Color.WHITE); //You color here
สถานการณ์ของฉันคือการตั้งค่าสีข้อความในเมนูตัวเลือก (เมนูแอพหลักแสดงบนปุ่มเมนูกด)
การทดสอบในAPI 16กับAppCompat-v7-27.0.2ห้องสมุดAppCompatActivity
สำหรับการMainActivity
และAppCompat
รูปแบบสำหรับการประยุกต์ใช้ในAndroidManifest.xml
styles.xml :
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="actionBarPopupTheme">@style/PopupTheme</item>
</style>
<style name="PopupTheme" parent="@style/ThemeOverlay.AppCompat.Light">
<item name="android:textColorSecondary">#f00</item>
</style>
ไม่ทราบว่าจะtextColorSecondary
มีผลกับองค์ประกอบอื่นหรือไม่ แต่จะควบคุมสีข้อความของเมนู
ฉันค้นหาตัวอย่างบางส่วนในหัวข้อ แต่ตัวอย่างข้อมูลแบบพร้อมใช้งานทั้งหมดไม่ทำงาน
ดังนั้นฉันต้องการตรวจสอบด้วยซอร์สโค้ดสำหรับไลบรารี appcompat-v7 (โดยเฉพาะกับโฟลเดอร์resของแพ็คเกจ. aar )
แม้ว่าในกรณีของฉันฉันใช้ Eclipse กับการพึ่งพา. explar ดังนั้นฉันสามารถเปลี่ยนสไตล์เริ่มต้นและตรวจสอบผลลัพธ์ ไม่ทราบวิธีการระเบิดไลบรารีที่จะใช้กับGradleหรือAndroid Studioโดยตรง มันสมควรได้รับการสอบสวนอีกครั้ง
ดังนั้นจุดประสงค์ของฉันคือหาสีใดในไฟล์res / values / values.xml ที่ใช้สำหรับข้อความเมนู (ฉันเกือบแน่ใจว่าสีอยู่ที่นั่น)
#f00
ค่าให้กับพวกเขาทั้งหมดsecondary_text_default_material_light
รายการสี@color/abc_secondary_text_material_light
ประเพณีถูกพบสำหรับBase.ThemeOverlay.AppCompat.Light
และPlatform.AppCompat.Light
และandroid:textColorSecondary
และในandroid:textColorTertiary
Base.ThemeOverlay.AppCompat.Light
android:textColorSecondary
ที่ผมพบว่าแอตทริบิวต์ที่ถูกต้องสุดท้ายคือTheme.AppCompat.Light
และไม่ใช่ThemeOverlay.AppCompat.Light
)Base.ThemeOverlay.AppCompat.Light
ฉันค้นหาในไฟล์เดียวสำหรับ มันมีลูกThemeOverlay.AppCompat.Light
มันมีบุตรThemeOverlay.AppCompat.Light
ฉันพบการใช้งานในBase.Theme.AppCompat.Light.DarkActionBar
ชุดรูปแบบเป็นactionBarPopupTheme
ค่าแอตทริบิวต์Theme.AppCompat.Light.DarkActionBar
เป็นลูกของการค้นพบBase.Theme.AppCompat.Light.DarkActionBar
ดังนั้นฉันสามารถใช้คุณลักษณะนั้นในstyles.xmlของฉันได้โดยไม่มีปัญหาThemeOverlay.AppCompat.Light
และเปลี่ยนandroid:textColorSecondary
คุณลักษณะโซลูชันของ Sephyไม่ทำงาน เป็นไปได้ที่จะแทนที่การปรากฏตัวของรายการเมนูตัวเลือกโดยใช้วิธีการที่อธิบายไว้ข้างต้น แต่ไม่ใช่รายการหรือเมนู ในการทำเช่นนั้นมี 3 วิธี:
ดูที่ปัญหา 4441: ธีมเมนูตัวเลือกที่กำหนดเองสำหรับเบาะแสเพิ่มเติม
ลองรหัสนี้ ....
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my_menu, menu);
getLayoutInflater().setFactory(new Factory() {
@Override
public View onCreateView(String name, Context context,
AttributeSet attrs) {
if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
try {
LayoutInflater f = getLayoutInflater();
final View view = f.createView(name, null, attrs);
new Handler().post(new Runnable() {
public void run() {
// set the background drawable
view.setBackgroundResource(R.drawable.my_ac_menu_background);
// set the text color
((TextView) view).setTextColor(Color.WHITE);
}
});
return view;
} catch (InflateException e) {
} catch (ClassNotFoundException e) {
}
}
return null;
}
});
return super.onCreateOptionsMenu(menu);
}
java.lang.IllegalStateException: A factory has already been set on this LayoutInflater
หากคุณต้องการตั้งค่าสีสำหรับรายการเมนูแต่ละรายการการปรับแต่งธีมของแถบเครื่องมือไม่ใช่วิธีที่เหมาะสม เพื่อให้บรรลุนี้คุณสามารถใช้ android: actionLayout และมุมมองแอ็คชั่นสำหรับรายการเมนู
ขั้นแรกให้สร้างไฟล์เลย์เอาต์ XML สำหรับมุมมองการกระทำ ในตัวอย่างนี้เราใช้ปุ่มเป็นมุมมองการกระทำ:
menu_button.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/menuButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Done"
android:textColor="?android:attr/colorAccent"
style="?android:attr/buttonBarButtonStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ในข้อมูลโค้ดข้างต้นเราใช้android:textColor="?android:attr/colorAccent"
ในการปรับแต่งสีข้อความของปุ่ม
จากนั้นในไฟล์ XML เลย์เอาต์ของคุณสำหรับเมนูรวมapp:actionLayout="@layout/menu_button"
ดังต่อไปนี้:
main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menuItem"
android:title=""
app:actionLayout="@layout/menu_button"
app:showAsAction="always"/>
</menu>
แทนที่onCreateOptionsMenu()
วิธีการล่าสุดในกิจกรรมของคุณ:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
MenuItem item = menu.findItem(R.id.menuItem);
Button saveButton = item.getActionView().findViewById(R.id.menuButton);
saveButton.setOnClickListener(view -> {
// Do something
});
return true;
}
... หรือส่วน:
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater){
inflater.inflate(R.menu.main_menu, menu);
MenuItem item = menu.findItem(R.id.menuItem);
Button saveButton = item.getActionView().findViewById(R.id.menuButton);
button.setOnClickListener(view -> {
// Do something
});
}
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับมุมมองการกระทำดูคู่มือนักพัฒนาซอฟต์แวร์ Android
นี่คือวิธีที่คุณสามารถสีรายการเมนูเฉพาะด้วยสีใช้งานได้กับทุกระดับ API:
public static void setToolbarMenuItemTextColor(final Toolbar toolbar,
final @ColorRes int color,
@IdRes final int resId) {
if (toolbar != null) {
for (int i = 0; i < toolbar.getChildCount(); i++) {
final View view = toolbar.getChildAt(i);
if (view instanceof ActionMenuView) {
final ActionMenuView actionMenuView = (ActionMenuView) view;
// view children are accessible only after layout-ing
actionMenuView.post(new Runnable() {
@Override
public void run() {
for (int j = 0; j < actionMenuView.getChildCount(); j++) {
final View innerView = actionMenuView.getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
if (resId == itemView.getId()) {
itemView.setTextColor(ContextCompat.getColor(toolbar.getContext(), color));
}
}
}
}
});
}
}
}
}
ด้วยการทำเช่นนั้นคุณทำให้เอฟเฟ็กเตอร์ตัวเลือกพื้นหลังหลวมนี่คือรหัสที่จะใช้ตัวเลือกพื้นหลังแบบกำหนดเองกับรายการเมนูลูกทั้งหมด
public static void setToolbarMenuItemsBackgroundSelector(final Context context,
final Toolbar toolbar) {
if (toolbar != null) {
for (int i = 0; i < toolbar.getChildCount(); i++) {
final View view = toolbar.getChildAt(i);
if (view instanceof ImageButton) {
// left toolbar icon (navigation, hamburger, ...)
UiHelper.setViewBackgroundSelector(context, view);
} else if (view instanceof ActionMenuView) {
final ActionMenuView actionMenuView = (ActionMenuView) view;
// view children are accessible only after layout-ing
actionMenuView.post(new Runnable() {
@Override
public void run() {
for (int j = 0; j < actionMenuView.getChildCount(); j++) {
final View innerView = actionMenuView.getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
// text item views
final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
UiHelper.setViewBackgroundSelector(context, itemView);
// icon item views
for (int k = 0; k < itemView.getCompoundDrawables().length; k++) {
if (itemView.getCompoundDrawables()[k] != null) {
UiHelper.setViewBackgroundSelector(context, itemView);
}
}
}
}
}
});
}
}
}
}
นี่คือฟังก์ชันตัวช่วยด้วย:
public static void setViewBackgroundSelector(@NonNull Context context, @NonNull View itemView) {
int[] attrs = new int[]{R.attr.selectableItemBackgroundBorderless};
TypedArray ta = context.obtainStyledAttributes(attrs);
Drawable drawable = ta.getDrawable(0);
ta.recycle();
ViewCompat.setBackground(itemView, drawable);
}
สำหรับการเปลี่ยนสีของข้อความคุณสามารถตั้งค่ามุมมองแบบกำหนดเองสำหรับ MenuItem จากนั้นคุณสามารถกำหนดสีของข้อความ
รหัสตัวอย่าง: MenuItem.setActionView ()