1

我想根据视图的选定状态动态选择 Drawable。我使用布尔状态而不是字符串,因为根据这篇文章不支持字符串。以下是代码详细信息:

attrs.xml

<declare-styleable name="StateView">
    <attr name="state_not_available" format="boolean" />
    <attr name="state_idle" format="boolean" />
    <attr name="state_busy" format="boolean" />
</declare-styleable>

selector_driver_state.xml

<selector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto">
    <item custom:state_not_available="true"
        android:drawable="@drawable/drawable_icon_not_available"/>
    <item custom:state_idle="true"
        android:drawable="@drawable/drawable_icon_idle"/>
    <item custom:state_busy="true"
        android:drawable="@drawable/drawable_icon_busy"/>
    <item android:drawable="@drawable/drawable_icon_busy" />
</selector>

状态视图.kt

class StateView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private var STATE_NOT_AVAILABLE = intArrayOf(R.attr.state_not_available)
    private var STATE_IDLE = intArrayOf(R.attr.state_idle)
    private var STATE_BUSY = intArrayOf(R.attr.state_busy)

    private var mStateNotAvail : Boolean = false
    private var mStateIdle : Boolean = false
    private var mStateBusy : Boolean = false

    init {
        initAttrs(context, attrs)
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        attrs?.let {
            val attrArr = context.obtainStyledAttributes(attrs, R.styleable.StateView)
            try {
                mStateNotAvail = attrArr.getBoolean(R.styleable.StateView_state_not_available, false)
                mStateIdle = attrArr.getBoolean(R.styleable.StateView_state_idle, false)
                mStateBusy = attrArr.getBoolean(R.styleable.StateView_state_busy, false)
            }
            finally {
                attrArr.recycle()
            }
        }
    }

fun setStateBusy(state: Boolean) {
        mStateNotAvail = false
        mStateIdle = false
        mStateBusy = state
        invalidate()
        requestLayout()
    }

    override fun onCreateDrawableState(extraSpace: Int): IntArray {

        val drawableStates = super.onCreateDrawableState(extraSpace + 1)
        if(mStateNotAvail)
            mergeDrawableStates(drawableStates, STATE_NOT_AVAILABLE)
        else if(mStateIdle)
            mergeDrawableStates(drawableStates, STATE_IDLE)
        else
            mergeDrawableStates(drawableStates, STATE_BUSY)
        return drawableStates
    }

用法:

<com.abc.package.components.StateView
    android:layout_width="20dp"
    android:layout_height="20dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:id="@+id/viewState"
    app:state_idle="true"                    ----> not working!
    android:layout_marginLeft="10dp"/>

问题是StateView没有渲染。我尝试以编程方式设置状态,但使用setStateBusy. 有什么线索吗?谢谢你。

4

1 回答 1

1
  1. 您不能将字符串属性与选择器 Drawable 一起使用。您需要为 StateView 定义一个自定义字符串属性app:state="Idle"并根据所选状态以编程方式更改可绘制对象。

    // attrs.xml 的变化

    <declare-styleable name="StateView"> <attr name="state" format="reference|string" /> </declare-styleable>

    // 布局文件的变化

    <com.abc.package.components.StateView app:state="Idle" ...

  2. StateView类中添加以下方法setState

    fun setState(state: String) { if(state?.equals("idle")){ imageView.setDrawable(R.drawable. drawable_icon_idle); } if(state?.equals("busy")){ imageView.setDrawable(R.drawable. drawable_icon_busy); } ...
    }

希望这能解决您的问题。现在您还可以从StateView.kt类中删除大部分行

于 2020-02-25T06:14:31.563 回答