Просмотр с пользовательским StateListDrawable не рендеринг - PullRequest
1 голос
/ 25 февраля 2020

Я хочу динамически выбрать 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>

StateView.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. Какие-либо ведет? Спасибо.

1 Ответ

1 голос
/ 25 февраля 2020
  1. Нельзя использовать атрибуты String с селектором Drawable. Вам необходимо определить пользовательский атрибут String app: state = "Idle" для StateView и программно изменить рисование на основе выбранного состояния.

    // изменения в атрибутах. xml

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

    // изменения в файле макета

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

  2. Добавить следующий метод setState в StateView класс

    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); } ...<br> }

Надеюсь, что это решит вашу проблему. Теперь вы также можете удалить большинство строк из StateView.kt class

...