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

自定义复合View中Button可见,但TextView/ImageView不可见求助

问题原因分析

你重写的addView(child: View?)只是FrameLayout众多addView重载方法中的一个。当系统添加TextView或ImageView时,会调用其他重载版本(比如addView(View, LayoutParams)、addView(View, int)等),这些方法没被重写,导致子View被直接添加到外层FrameLayout中,而非目标的holder CardView。外层FrameLayout上的标题CardView会遮挡这些子View,或者因布局层级问题导致它们无法正常显示。

Button能正常显示是偶然情况——系统对Button的布局处理刚好调用了你重写的那个addView方法。

解决方案

重写所有FrameLayout的addView重载方法,确保所有子View都被添加到holder CardView中:

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import androidx.cardview.widget.CardView


class CompoundCardView : FrameLayout{

    private var childView:CardView? = null

    private var heading:String? = null
        set(value) {
            field = value
            invalidate()
            requestLayout()
        }
        get() = field

    constructor(context: Context) : super(context) {
        init(context, null)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(context, attrs)
    }


    constructor(context: Context,
                attrs: AttributeSet,
                defStyle: Int) : super(context, attrs, defStyle) {
        init(context, attrs)
    }
    
    private fun init(context: Context, attrs: AttributeSet?) {
        context.theme.obtainStyledAttributes(attrs,R.styleable.CompoundCardView,0,0).apply {
            try {
                heading = getString(R.styleable.CompoundCardView_heading)
            }finally {
                recycle()
            }
        }

        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        inflater.inflate(R.layout.compaund_card_view,this,true)
        childView = findViewById(R.id.holder)
        val header:TextView = findViewById(R.id.header)
        header.text = heading
    }

    // 重写所有addView重载方法,统一将子View添加到holder中
    override fun addView(child: View?) {
        childView?.addView(child)
        requestLayout()
        invalidate()
    }

    override fun addView(child: View?, index: Int) {
        childView?.addView(child, index)
        requestLayout()
        invalidate()
    }

    override fun addView(child: View?, params: ViewGroup.LayoutParams?) {
        childView?.addView(child, params)
        requestLayout()
        invalidate()
    }

    override fun addView(child: View?, width: Int, height: Int) {
        childView?.addView(child, width, height)
        requestLayout()
        invalidate()
    }

    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
        childView?.addView(child, index, params)
        requestLayout()
        invalidate()
    }
}       
额外优化建议
  • 给holder CardView添加app:contentPadding属性,避免子View紧贴边框,提升视觉体验;
  • 初始化childView后增加非空判断,避免空指针异常。

内容的提问来源于stack exchange,提问作者Samaresh Sautia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 03:58:38