Android技术求助:将Button样式改为Spinner样式并使用自定义背景
Hey, I get exactly what you need here—keeping the Button component intact while making it look like a Spinner, since you’ve already put in the work for PopupMenu icons and drawable backgrounds. Let’s walk through a solid, modern solution that avoids those outdated 2011 workarounds:
1. Build a Custom Spinner-Style Drawable Background
First, create a selector drawable (name it something like btn_spinner_background.xml) in your res/drawable folder. This will mimic the Spinner's visual states (default, pressed, disabled) and include that classic dropdown arrow:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Pressed state --> <item android:state_pressed="true"> <layer-list> <item> <shape android:shape="rectangle"> <solid android:color="@color/spinner_pressed_bg"/> <corners android:radius="4dp"/> </shape> </item> <item android:gravity="center_vertical|right" android:right="12dp"> <vector android:width="24dp" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24"> <path android:fillColor="@color/white" android:pathData="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"/> </vector> </item> </layer-list> </item> <!-- Default state --> <item> <layer-list> <item> <shape android:shape="rectangle"> <solid android:color="@color/spinner_default_bg"/> <stroke android:color="@color/spinner_border" android:width="1dp"/> <corners android:radius="4dp"/> </shape> </item> <item android:gravity="center_vertical|right" android:right="12dp"> <vector android:width="24dp" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24"> <path android:fillColor="@color/text_primary" android:pathData="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"/> </vector> </item> </layer-list> </item> </selector>
Tweak the colors, corner radii, and arrow style to match your app's design—you can swap the vector icon for a PNG if you prefer.
2. Apply the Background to Your Button
In your layout file, assign this drawable to your Button and adjust the layout properties to match Spinner behavior:
<Button android:id="@+id/spinner_style_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/btn_spinner_background" android:gravity="center_vertical|left" android:paddingEnd="40dp" <!-- Give the dropdown arrow space --> android:text="Select an option" android:textColor="@color/text_primary"/>
3. Keep Your Existing PopupMenu Logic
Since you’ve already sorted out PopupMenu icon display, just hook up the Button click listener as you normally would:
val spinnerBtn = findViewById<Button>(R.id.spinner_style_btn) spinnerBtn.setOnClickListener { val popupMenu = PopupMenu(this, spinnerBtn) // Use your existing menu inflation logic here popupMenu.menuInflater.inflate(R.menu.your_custom_menu, popupMenu.menu) // Update Button text when an option is selected popupMenu.setOnMenuItemClickListener { item -> spinnerBtn.text = item.title true } popupMenu.show() }
Quick Optimization Tips
- Match system Spinner dimensions: Check your platform's default Spinner padding/minWidth values and apply them to your Button for consistency.
- Add dark mode support: Create a
drawable-nightfolder and duplicate the background drawable with dark-mode color values. - Disable ripple if needed: If you don’t want the standard Button ripple effect, add
android:foreground="null"to the Button tag.
This approach keeps your Button component fully functional (drawable background, PopupMenu integration) while making it visually identical to a Spinner—no outdated hacks required.
内容的提问来源于stack exchange,提问作者jonb

