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

时间:2018-08-15 19:06:22

标签: android canvas android-linearlayout android-canvas

我正在构建一个MultiStateToggle按钮。

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

超类ToggleButton仅包含一些常量。它扩展了LinearLayout

有人知道,为什么在这个LinearLayout子类中无法绘制图形?

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"
    }
}

1 个答案:

答案 0 :(得分:0)

当在主要构造函数调用中调用Kotlins的init块时,我的Paint尚未初始化。