I've added rounded corners to a PopupMenu
and it looks good, except now when I press a menu item, I get the ugly effect shown here:
In this example, while my finger is touching the third item, Android adds a default color behind the item, which shows through at the rounded corners. It also adds a rounded background to the item text, which partially covers the "glow" around the radio button.
This is my XML style for rounding the corners of the PopupMenu
:
<style name="popover" parent="@android:style/Widget.PopupMenu">
<item name="android:itemBackground">@android:color/transparent</item>
<item name="android:colorBackground">@android:color/transparent</item>
<item name="android:background">@drawable/alert_rounded_dark</item>
<item name="android:textColor">#F9F9F9</item>
<item name="android:textColorSecondary">#F9F9F9</item>
<item name="colorAccent">#F9F9F9</item>
</style>
And alert_rounded_dark.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#2B2B2B" />
<corners android:radius="10dp" />
</shape>
It looks like Android is applying the rounded background style to the subviews of the popup menu, including the menu items and the menu item text. I tried to stop that by setting itemBackground
to @android:color/transparent
or @null
, but that had no effect.
I tried changing the background
attribute to windowBackground
, popupBackground
or panelBackground
, but then the whole PopupMenu
and its items were transparent.
I had a similar issue when rounding the corners of ListView
rows, which I solved with this function of ListView
:
this.listView?.setSelector(android.R.color.transparent)
I think this corresponds to the listSelector
XML attribute, but I don't see a similar function or attribute in the class reference for PopupMenu
, and using the listSelector
attribute for a PopupMenu
does nothing.
Is there another way to visually clean this up? I think stopping the inheritance of the rounded corner background and removing the pressed color would be best, but addressing either one should help a lot.
UPDATE
I found that changing itemBackground
to the same color as the menu background stopped the system color from appearing behind items when pressing them (the four light gray corners you see in the picture), but that killed the rounded corners by adding an opaque, square background to every item. Then I tried setting itemBackground
to a drawable selector that sets every state to the alert_rounded_dark
drawable, to preserve the rounded corners, but that didn't suppress the system pressed color like setting a background color did.
CodePudding user response:
How do you apply the popover
style to your PopupMenu?
If you use a ContextThemeWrapper
, you can't directly apply PopupMenu style.
You need to assign your popover
style to the popupMenuStyle
attribute in the theme overlay. Here is how you can do it:
styles.xml
<style name="ThemeOverlay.App.PopupMenu" parent="">
<!-- if using android.widget.PopupMenu -->
<item name="android:popupMenuStyle">@style/PopupMenu</item>
<!-- if using androidx.appcompat.widget.PopupMenu -->
<item name="popupMenuStyle">@style/PopupMenu</item>
<!-- Other attributes -->
<item name="android:textColor">#F9F9F9</item>
<item name="android:textColorSecondary">#F9F9F9</item>
<item name="colorAccent">#F9F9F9</item>
</style>
<style name="PopupMenu" parent="@android:style/Widget.PopupMenu">
<item name="android:popupBackground">@drawable/alert_rounded_dark</item>
</style>
And use it like so:
val menu = PopupMenu(
// Using "ContextThemeWrapper" for PopupMenu customization
ContextThemeWrapper(context, R.style.ThemeOverlay_App_PopupMenu),
view // Your anchor view
)
menu.inflate(R.menu.your_menu_id)
menu.show()
Here is how it looks on my end:
Bonus:
If you wish to further customize RadioButton
inside the PopupMenu
, you can add radioButtonStyle
attribute to the theme overlay, like so:
<style name="ThemeOverlay.App.PopupMenu" parent="">
...
<item name="radioButtonStyle">@style/YourCustomRadioButton</item>
</style>