You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为RecyclerView中Button添加渐变背景时出现Inflation错误

问题:MaterialComponents主题下RecyclerView列表项Button加载自定义渐变背景崩溃

在使用MaterialComponents主题、最低SDK为API 21的环境中,为RecyclerView书籍列表项的Button设置带渐变效果的自定义背景(roundbutton.xml)时,出现android.view.InflateException布局加载错误。


相关代码

book_item.xml(列表项布局)

. . .

    <Button
        android:id="@+id/read_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:text="Start Reading"

        android:background="@drawable/roundbutton"
        app:backgroundTint="@null" />
    . . .

roundbutton.xml(自定义背景Drawable)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:endColor="@color/dark_orange"
        android:startColor="@color/orange"
        android:angle="200" />

    <corners android:bottomRightRadius="100px"
        android:bottomLeftRadius="100px"
        android:topRightRadius="100px"
        android:topLeftRadius="100px"/>

</shape>

BookAdapterOne.kt(RecyclerView适配器)

class BookAdapterOne(
    private val context: Context,
    private var data: List<Book>,
    private val bookClickListener: BookClickListener
) : RecyclerView.Adapter<BookAdapterOne.ItemViewHolder>() {

    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val title: TextView = view.findViewById(R.id.book_title)
        val author: TextView = view.findViewById(R.id.book_author)
        val description: TextView = view.findViewById(R.id.book_description)
        val read_btn: Button = view.findViewById(R.id.read_btn)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val adapterLayout = LayoutInflater.from(parent.context)
            .inflate(R.layout.book_item, parent, false)

        return ItemViewHolder(adapterLayout)
    }

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = data[position]
        holder.title.text = item.title
        holder.author.text = item.author
        holder.description.text = item.description

        holder.read_btn.setOnClickListener {
            bookClickListener.onBookClickListener(item)
        }
    }
}

错误日志

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sapphire.littlered, PID: 5920
android.view.InflateException: Binary XML file line #51: Error inflating class Button
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
at com.sapphire.littlered.adapter.BookAdapterOne.onCreateViewHolder(BookAdapterOne.kt:33)
at com.sapphire.littlered.adapter.BookAdapterOne.onCreateViewHolder(BookAdapterOne.kt:18)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1077)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1702)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1556)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1465)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1702)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1556)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1465)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:16992)
at android.view.ViewGroup.layout(ViewGroup.java:5409)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2483)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2185)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1314)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7057)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:829)
at android.view.Choreographer.doCallbacks(Choreographer.java:606)
at android.view.Choreographer.doFrame(Choreographer.java:576)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:815)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(
I/Process: Sending signal. PID: 5920 SIG: 9

解决方案

核心原因

使用MaterialComponents主题时,系统会自动将默认Button替换为MaterialButton,而MaterialButton对自定义android:background的兼容性较差——即使设置了app:backgroundTint="@null",在API21这类低版本系统中仍会因内部视图逻辑冲突导致Inflate失败。

修复步骤

  1. 替换Button为AppCompatButton
    将布局中的Button改为androidx.appcompat.widget.AppCompatButton,它兼容API21+,且能正常加载自定义shape背景,无需额外设置backgroundTint:

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/read_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:text="Start Reading"
        android:background="@drawable/roundbutton" />
    
  2. 统一单位为dp
    将roundbutton.xml中的px单位改为dp,保证不同分辨率设备显示一致,同时简化圆角写法:

    <corners android:radius="100dp"/>
    
  3. 验证颜色资源
    确认@color/orange和@color/dark_orange已在res/values/colors.xml中正确定义,避免因资源缺失导致加载错误:

    <color name="orange">#FF9800</color>
    <color name="dark_orange">#F57C00</color>
    

备选方案(若坚持用MaterialButton)

如果必须使用MaterialButton,可以通过代码动态设置背景:

// 在Adapter的onBindViewHolder中添加
val drawable = ContextCompat.getDrawable(context, R.drawable.roundbutton)
holder.read_btn.background = drawable

但此方法在API21上的兼容性仍不如AppCompatButton稳定。


内容的提问来源于stack exchange,提问作者Luke Wardford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:35:19