Android自定义图文按钮:背景与文本边框等实现疑问
Hey there! Let's tackle your custom button problems one by one—sounds like you're hitting the limits of the default Button widget, which is super common when you need more control over visuals. Here's how to fix each issue and build the button you want:
1. Fixing "Can't set both border and image via android:background"
The android:background attribute can only take one drawable at a time, but you can stack multiple drawables using a layer-list. Create a new drawable file (e.g., res/drawable/custom_button_bg.xml) with this structure:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Bottom layer: Border --> <item> <shape android:shape="rectangle"> <stroke android:width="2dp" android:color="#FF0000" /> <!-- Your border color --> <corners android:radius="8dp" /> <!-- Optional rounded corners --> </shape> </item> <!-- Top layer: Image (adjust gravity to position it) --> <item android:drawable="@drawable/your_button_image" android:gravity="center|left" android:left="16dp" /> <!-- Add padding to avoid overlapping text --> </layer-list>
Then set this as your button's background:
<Button android:id="@+id/custom_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/custom_button_bg" android:text="Your Button Text" android:paddingStart="48dp" /> <!-- Padding to make space for the image -->
2. Adding a Border to Button Text
The default Button doesn't support text borders directly, but you have two solid options:
- Option 1: Use a
TextViewinstead (it works just like a button!)
Use aSpannableStringin your code to add a stroke to the text:val buttonText = "Your Button Text" val spannable = SpannableString(buttonText) spannable.setSpan( object : CharacterStyle() { override fun updateDrawState(tp: TextPaint) { tp.style = Paint.Style.STROKE tp.strokeWidth = 2f tp.color = Color.BLACK // Text border color } }, 0, buttonText.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE ) yourTextView.text = spannable yourTextView.setOnClickListener { /* Your click logic */ } - Option 2: Use a custom font with outline
If you don't want to mess with code, you can use a pre-made font that already has a border effect.
3. Can You Set a Layout Inside a Button?
Technically, you can't add child views directly to a Button (it's a subclass of TextView, which doesn't support child views). But the better approach is to wrap your desired layout in a clickable container (like ConstraintLayout or LinearLayout) and treat that as your custom button. This gives you full control over text, image, and any other elements:
<ConstraintLayout android:id="@+id/custom_button_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:focusable="true" android:background="@drawable/custom_button_bg"> <!-- Reuse the border drawable here --> <ImageView android:id="@+id/button_icon" android:layout_width="24dp" android:layout_height="24dp" android:src="@drawable/your_button_image" app:layout_constraintStart_toStartOf="parent" app:layout_constraintCenterVertical_toCenterOf="parent" android:paddingStart="16dp" /> <TextView android:id="@+id/button_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Your Button Text" app:layout_constraintStart_toEndOf="@id/button_icon" app:layout_constraintCenterVertical_toCenterOf="parent" android:paddingHorizontal="16dp" android:paddingVertical="8dp" /> </ConstraintLayout>
Then in your code, set the click listener on the container:
custom_button_container.setOnClickListener { // Your button click logic here }
This approach is way more flexible than trying to force the Button widget to do things it wasn't designed for.
内容的提问来源于stack exchange,提问作者filol

