尽管调用了 onDraw,但 LinearLayout 未绘制

LinearLayout is not drawing though onDraw is called

我正在构建一个 MultiStateToggle 按钮。

为了突出显示选中状态,我需要绘制一个恰好与按钮大小相同的矩形。这个矩形滑动到当前状态。因此我需要画画,但无论我做什么,即使调用了 onDraw,我也看不到任何变化。

superclass ToggleButton 只包含一些常量。它扩展 LinearLayout!

有谁知道,为什么在这个 LinearLayout 子 class 中绘图不起作用?

class MultiStateToggleButton : ToggleButton {

    //region Variables

    private val mHighlightPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)

    @DrawableRes
    private val iSelectableItemBackgroundDrawableResId: Int

    private val mButtons = mutableListOf<Button>()

    //endregion

    constructor(context: Context) : this(context, Any() as AttributeSet)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        val mTypedValue = TypedValue()
        context.theme.resolveAttribute(R.attr.colorPrimary, mTypedValue, true)
        val iPrimaryColor = mTypedValue.data

        context.theme.resolveAttribute(R.attr.colorPrimary, mTypedValue, true)
        val iPrimaryDarkColor = mTypedValue.data

        setBackgroundColor(iPrimaryDarkColor)

        context.theme.resolveAttribute(R.attr.colorAccent, mTypedValue, true)
        val iAccentColor = mTypedValue.data

        val mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.MultiStateToggleButton)

        foregroundColor = mTypedArray.getColor(R.styleable.MultiStateToggleButton_foregroundColor, iPrimaryColor)
        highlightColor = mTypedArray.getColor(R.styleable.MultiStateToggleButton_highlightColor, iAccentColor)

        val mTexts = mTypedArray.getTextArray(R.styleable.MultiStateToggleButton_elements)
        if (mTexts != null) {
            val iSelectedElement = mTypedArray.getInt(R.styleable.MultiStateToggleButton_selectedElement, 0)
            setElements(Array(mTexts.size) { i ->
                mTexts[i].toString()
            }, iSelectedElement)
        }

        mTypedArray.recycle()
    }

    init {
        val mTypedValue = TypedValue()
        context.theme.resolveAttribute(android.R.attr.selectableItemBackground, mTypedValue, true)
        iSelectableItemBackgroundDrawableResId = mTypedValue.resourceId

        mHighlightPaint.apply {
            color = highlightColor
            style = Paint.Style.FILL
        }
    }

    //region Public Variables

    override var selectedElement: Int = 0
        set(value) {
            selectButton(value)
            field = value
            super.selectedElement = value
        }

    //endregion

    //region Methods

    fun setElements(texts: Array<String>) {
        removeAllViews()
        mButtons.clear()

        texts.forEachIndexed { i, text ->
            val mButton = Button(context).apply {
                layoutParams = LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, LAYOUT_WEIGHT_EQUAL)
                setBackgroundResource(iSelectableItemBackgroundDrawableResId)
                setText(text)
                setTextColor(textColor)
                setOnClickListener { selectedElement = i }
            }

            mButtons.add(mButton)
            addView(mButton)
        }
    }

    fun setElements(texts: Array<String>, selectedItem: Int) {
        setElements(texts)

        selectButton(selectedItem)
    }

    override fun setEnabled(enabled: Boolean) {
        for (i in 0 until childCount) {
            getChildAt(i).isEnabled = enabled
        }
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.drawRect(0f, 0f, 30f, 30f, mHighlightPaint)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)

        setWillNotDraw(false)
    }

    override fun onSaveInstanceState(): Parcelable {
        return Bundle().apply {
            putParcelable(KEY_INSTANCE_STATE, super.onSaveInstanceState())
            putInt(KEY_SELECTED_BUTTON, selectedElement)
        }
    }

    override fun onRestoreInstanceState(state: Parcelable?) {
        var mRestoredState: Parcelable? = state

        if (state is Bundle) {
            selectButton(state.getInt(KEY_SELECTED_BUTTON))
            mRestoredState = state.getParcelable(KEY_INSTANCE_STATE)
        }

        super.onRestoreInstanceState(mRestoredState)
    }

    private fun selectButton(position: Int) {
        if (mButtons.isNotEmpty()) {
            if (position >= mButtons.size) {
                throw IndexOutOfBoundsException("Position was $position but there are only ${mButtons.size} Buttons.")
            }

            getChildAt(selectedElement).isEnabled = true
            getChildAt(position).isEnabled = false

            invalidate()
        }
    }

    //endregion

    companion object {
        private const val KEY_SELECTED_BUTTON = "mtb_selected_button"
        private const val KEY_INSTANCE_STATE = "mtb_instance_state"
    }
}

由于 Kotlins 的 init 块在主构造函数调用时被调用,因此我的 Paint 未初始化。