[英]How to use Android Selector to change item color in PopupMenu?
I have a button in my OptionMenu which when touched will open a popup menu of items which are fetched at run time and added programmatically (so can't use hard coded xml menu items).我的 OptionMenu 中有一个按钮,当触摸它时会打开一个弹出菜单,其中包含在运行时获取并以编程方式添加的项目(因此不能使用硬编码的 xml 菜单项)。 I want to highlight a subset of these items according to their value, I used what is suggested here: How to customize item background and item text color inside NavigationView?我想根据它们的值突出显示这些项目的一个子集,我使用了这里建议的内容:如何在 NavigationView 中自定义项目背景和项目文本颜色? to try and get the items to be colored differently.尝试使项目具有不同的颜色。 However, all of the items are colored the same despite the isChecked()
value being different.但是,尽管isChecked()
值不同,但所有项目的颜色都相同。
Here is a small working example of the issue:这是该问题的一个小工作示例:
MainActivity.java主活动.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.actionbar_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id) {
case R.id.action_bar_button:{
showMenu();
return true;
}
}
return super.onOptionsItemSelected(item);
}
private void showMenu() {
View v = findViewById(R.id.action_bar_button);
Context wrapper = new ContextThemeWrapper(this, R.style.MyPopupMenu);
PopupMenu popupMenu = new PopupMenu(wrapper, v);
//Sample items to demonstrate the issue. I want the background to be red if false, blue if true
Map<String, Boolean> list = new HashMap<>();
list.put("Item 1", true);
list.put("Item 2", false);
list.put("Item 3", true);
for(Map.Entry<String, Boolean> entry : list.entrySet()){
String msg = entry.getKey();
MenuItem item = popupMenu.getMenu().add(msg).setCheckable(true).setChecked(entry.getValue());
System.out.println(item.getTitle() + ": " + item.isChecked());
}
popupMenu.show();
}
styles.xml contains: style.xml包含:
<style name="MyPopupMenu" parent="Widget.AppCompat.PopupMenu">
<item name="android:itemBackground">@drawable/menu_item_background</item>
</style>
actionbar_menu.xml actionbar_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/action_bar_button"
android:title="List"
android:icon="@drawable/ic_launcher_foreground"
app:showAsAction="always" />
</menu>
colors.xml contains: color.xml包含:
<color name="red">#ff0000</color>
<color name="blue">#0000FF</color>
And the menu_item_background.xml和menu_item_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue" android:state_checked="true"/>
<item android:drawable="@color/red" android:state_checked="false"/>
</selector>
However, when I run this I get the following:但是,当我运行它时,我得到以下信息:
As you can see although the isChecked
state of Item 1 and 3 is true, they still appear red.如您所见,尽管 Item 1 和 3 的isChecked
状态为真,但它们仍然显示为红色。 The logcat output confirms this. logcat 输出证实了这一点。
As an experiment I changed the menu_item_background.xml
to use the android:state_enabled
instead of checked and it works as expected:作为一项实验,我将menu_item_background.xml
更改为使用android:state_enabled
而不是检查,它按预期工作:
What's going on here?这里发生了什么? Why doesn't this work with android:state_checked
?为什么这不适用于android:state_checked
?
Thanks for your help.谢谢你的帮助。
If your main motive is to highlight the selected item or similar kind of problem.如果您的主要动机是突出显示所选项目或类似问题。 I would like to suggest as one of the solutions which worked for me to use spinner, which Popup Menu provides a similar dropdown option as Spinner, with a custom layout for dropdown, and change the background color at getDropDownView()
at the adapter for the spinner.我想建议作为对我有用的 Spinner 的解决方案之一,它的 Popup Menu 提供了与 Spinner 类似的下拉选项,具有下拉自定义布局,并在适配器的getDropDownView()
处更改背景颜色纺纱机。
R.layout.spinner_item.xml R.layout.spinner_item.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_context"
android:layout_height="wrap_content"
android:visibility="gone"
/>
R.layout.spinner_drop_down.xml R.layout.spinner_drop_down.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
>
<TextView
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="wrap_content"
android:layout_height="?attr/dropdownListPreferredItemHeight"
android:id="@+id/spinner_dropdown_text"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"/>
</LinearLayout>
UI Design界面设计
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<!--Some Layouts-->
<Spinner
android:id="@+id/spinner"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:background="@drawable/icon"
android:gravity="center"
android:textDirection="firstStrongLtr"
android:overlapAnchor="false"/>
<!--Some More Layouts-->
</LinearLayout>
MainActivity.kt主活动.kt
val spinner = findViewById<Spinner>(R.id.spinner)
val spinnerData = arrayListOf<String>("Item 1", "Item 2", "Item 3")
val arrayAdapter = object : ArrayAdapter<String>(activity!!.applicationContext,R.layout.spinner_item, spinnerData) {
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val spinnerItem = layoutInflater.inflate(R.layout.spinner_drop_down, null)
val dropDownText = spinnerItem.findViewById<TextView>(R.id.spinner_dropdown_text)
dropDownText.text = spinnerData[position]
val selected = spinner.selectedItemPosition
if (position == selected) spinnerItem.setBackgroundColor(Color.GRAY)
return spinnerItem
}
}
arrayAdapter.setDropDownViewResource(R.layout.spinner_drop_down)
spinner.adapter = arrayAdapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
//Do whatever you want to do when Item selected
}
override fun onNothingSelected(parent: AdapterView<*>) {
//Do whatever you want to do when No Item selected
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.