Spinner получает нулевой адаптер при настройке записей через привязку данных - PullRequest
1 голос
/ 05 мая 2020

Я добавляю записи в AppCompatSpinner в android, используя привязку данных следующим образом:

   <androidx.appcompat.widget.AppCompatSpinner
        android:id="@+id/spinner2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/textInputLayout14"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout14"
        android:entries="@{viewModel.arrays}"
        app:selectedValue="@={viewModel.beneficiary.mandal}"
        />

И свойство массивов в ViewModel равно:

private String[] arrays=new String[]{"Hello","Hi","Bye"};
    @Bindable
    public String[] getArrays() {
        return arrays;
    }

    public void setArrays(String[] arrays) {
        this.arrays = arrays;
    }

Но проблема в том, что я получаю нулевой адаптер в Binding adapter:

 @BindingAdapter(value = {"selectedValue", "selectedValueAttrChanged"}, requireAll = false)
    public static void bindSpinnerData(AppCompatSpinner pAppCompatSpinner, String newSelectedValue, final InverseBindingListener newTextAttrChanged) {
        pAppCompatSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                newTextAttrChanged.onChange();
                Log.d(TAG, "onItemSelected: "+newSelectedValue);
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        if (newSelectedValue != null) {
            if(pAppCompatSpinner.getAdapter()!=null) {
                int pos = ((ArrayAdapter<String>) pAppCompatSpinner.getAdapter()).getPosition(newSelectedValue);
                pAppCompatSpinner.setSelection(pos, true);
            }else{
                Log.d(TAG, "Adapter NULL: ");
            }
        }
    }


    @InverseBindingAdapter(attribute = "selectedValue", event = "selectedValueAttrChanged")
    public static String captureSelectedValue(AppCompatSpinner pAppCompatSpinner) {
        return (String) pAppCompatSpinner.getSelectedItem();
    }

Я получаю нулевой адаптер, и выбранное значение также не отражается в viewmodel. А также, когда я устанавливаю записи с использованием @array/stringArr, он работает без проблем

1 Ответ

0 голосов
/ 06 мая 2020

Вот код, который я использовал для привязки Spinner в XML с BindingAdapter. XML:

<data>
    <import type="java.util.List" />
    <variable
        name="stateData"
        type="List&lt;com.xyz.model.remote.result.State>" />
</data>

<androidx.appcompat.widget.AppCompatSpinner
    android:id="@+id/spState"
    android:layout_width="0dp"
    android:layout_height="@dimen/_30sdp"
    android:layout_marginTop="@dimen/_5sdp"
    android:backgroundTint="@color/textColor"
    android:minWidth="0dp"
    android:minHeight="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/ivState"
    app:layout_constraintTop_toTopOf="parent"
    bind:listitem="@layout/item_view"
    bind:onStateSelected="@{viewModel.onStateSelectedListener}"
    bind:selectedStateId="@={viewModel.signUpFormFields.stateId}"
    bind:states="@{stateData}" />

BindingAdapter.kt

@BindingAdapter(
    value = ["states", "defaultSelectedId", "onStateSelected", "selectedStateId", "selectedStateIdAttrChanged"],
    requireAll = false
)
@JvmStatic
fun bindStateSpinnerEntries(
    spinner: AppCompatSpinner,
    stateList: List<State>? = arrayListOf(),
    selectedId: Int? = -1,
    itemSelectedListener: AdapterView.OnItemSelectedListener,
    newId: Int?,
    idAttrChanged: InverseBindingListener
) {

    if (stateList == null) {
        val tempList = arrayListOf<State>()
        tempList.add(0, State(-1, -1, spinner.context.getString(R.string.login_state_hint)))
        spinner.adapter = StateSpAdapter(
            spinner.context,
            R.layout.item_dropdown,
            R.layout.item_view,
            tempList
        )
        spinner.setSelection(0)
        return
    }
    (stateList as ArrayList).add(
        0,
        State(-1, -1, spinner.context.getString(R.string.login_state_hint))
    )
    spinner.adapter = StateSpAdapter(
        spinner.context,
        R.layout.item_dropdown,
        R.layout.item_view,
        stateList
    )
    var selectedPos = 0
    if (selectedId != null) {
        for (state in stateList) {
            if (state.id == selectedId) {
                break
            }
            selectedPos++
        }
    }

    if (selectedPos < stateList.size) spinner.setSelection(selectedPos) else spinner.setSelection(
        0
    )
    spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onItemSelected(
            parent: AdapterView<*>,
            view: View,
            position: Int,
            id: Long
        ) {
            idAttrChanged.onChange()
            itemSelectedListener.onItemSelected(parent, view, position, id)
        }

        override fun onNothingSelected(parent: AdapterView<*>) {}
    }
}

@InverseBindingAdapter(
    attribute = "selectedStateId",
    event = "selectedStateIdAttrChanged"
)
@JvmStatic
fun captureSelectedStateId(powerSpinnerView: AppCompatSpinner): Int {
    return (powerSpinnerView.selectedItem as State).id
}

ViewModel

Наблюдать за слушателем изменения состояния.

val onStateSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onNothingSelected(parent: AdapterView<*>?) {

        }

        override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            stateReceived.postValue(true)
            errState.postValue(false)
        }
    }

Во фрагменте наблюдать и связывать список состояний.

mFragmentBinding.stateData = stateList
...