Проверено RadioButton Recycling - PullRequest
       28

Проверено RadioButton Recycling

0 голосов
/ 02 марта 2019

Я добавляю радиогруппы программно в мой обзор переработчика, и он работает нормально.Но когда я проверяю это и прокручиваю просмотрщик, он теряет проверенные радиостанции.

Я видел много способов и примеров решений, но я не могу достичь этого.Это было несколько дней подряд.

Я сохраняю проверенную радиостанцию ​​в модели, как вы можете видеть в коде ниже.

Адаптер:

@Override
public void onBindViewHolder(final NROptionLineHolder holder, int position) {

    holder.priceGroup.removeAllViews();
    holder.priceGroup.setOnCheckedChangeListener(null);

    int id = (position+1)*100;
    checklistModel = mChecklists.get(position);
    holder.packageName.setText(checklistModel.getTitle());

    for(String price : checklistModel.getQuestions()){
        RadioButton rb = new RadioButton(NROptionLineAdapter.this.context);
        rb.setId(id++);
        rb.setText(price);
        holder.priceGroup.addView(rb);
    }
    holder.priceGroup.check(checklistModel.getSelectedId());

    holder.priceGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            checklistModel.setSelectedId(checkedId);
            Log.d(TAG, "onCheckedChanged: " + checkedId);
        }
    });

}

Держатель

    OnNROptionListener onNROptionListener;

    public NROptionLineHolder(View itemView, OnNROptionListener onNROptionListener) {
        super(itemView);

        packageName = itemView.findViewById(R.id.package_name);
        priceGroup = itemView.findViewById(R.id.price_grp);

//        priceGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
//            @Override
//            public void onCheckedChanged(RadioGroup radioGroup, int i) {
//
//                Log.d(TAG, "onCheckedChanged: " + radioGroup.getCheckedRadioButtonId() + " " + i);
//            }
//        });

        this.onNROptionListener = onNROptionListener;
        itemView.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        onNROptionListener.onNROptionClick(getAdapterPosition());
    }

    public interface OnNROptionListener {
        void onNROptionClick(int position);
    }
}

РЕДАКТИРОВАТЬ 1 - Радиогруппа

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/package_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <RadioGroup
        android:id="@+id/price_grp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/package_name"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:orientation="horizontal"/>
</android.support.constraint.ConstraintLayout>

РЕДАКТИРОВАТЬ 2

В соответствии с просьбой, вот важный код из моего ChecklistActivity

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_checklist);

    intent = getIntent();
    size = intent.getIntExtra("size", 0);
    nr = intent.getIntExtra("nr", 0);

    Log.d(TAG, "Checklist Activity - Qtd Questões: " + size);
    Log.d(TAG, "Checklist Activity - NR: " + nr);

    btnSaveCheck = findViewById(R.id.btnSaveChecklist);

    mRecyclerView = findViewById(R.id.package_lst);
    setupRecycler();

    btnSaveCheck.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "Sucesso", Toast.LENGTH_SHORT).show();
        }
    });
}

private void setupRecycler() {

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(layoutManager);

    setupList();

    mAdapter = new NROptionLineAdapter(data, this, getApplication());
    mRecyclerView.setAdapter(mAdapter);

}

private void setupList(){
    data = new ArrayList<>();

    class setupList extends AsyncTask<Void, Void, List<MRNrOption>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected List<MRNrOption> doInBackground(Void... voids) {

            list = DatabaseClient
                    .getInstance(getApplicationContext())
                    .getAppDatabase()
                    .mrNrOptionDAO()
                    .loadAllByNRId(nr);
            return list;

        }

        @Override
        protected void onPostExecute(List<MRNrOption> list) {
            super.onPostExecute(list);

            List<String> priceList = new ArrayList<>();
            priceList.add("Sim");
            priceList.add("Não");
            priceList.add("Não se Aplica");

            for (int i=0; i<list.size(); i++) {
                Log.d(TAG, "NRs Activity - Adding To List: " + list.get(i).getTitle());
                data.add(new Checklist(
                        list.get(i).getTitle(),
                        priceList)
                );

                mAdapter.notifyDataSetChanged();
            }

        }
    }

    setupList lm = new setupList();
    lm.execute();
}

RecyclerView with RadioButtons

РЕДАКТИРОВАТЬ 3 - Важно

Радиогруппы и радиокнопки генерируются программно, потому что я получаю все вопросы с сервера, количество вопросов различается в зависимости от предыдущих выборов, сделанных пользователем, поэтому мне это нужно.

РЕДАКТИРОВАТЬ 4

GIF для улучшения визуализации проблемы

РЕДАКТИРОВАТЬ 5 - Контрольный список Модель класса

    public class Checklist {

    String title;
    List<String> questions;
    boolean isRadioButtonAdded;
    int selectedId;

    public Checklist(String title, List<String> questions) {
        this.title = title;
        this.questions = questions;
    }

    public Checklist(){}

    public boolean getIsAdded(){
        return isRadioButtonAdded;
    }

    public void setIsAdded(boolean isAdded){
        this.isRadioButtonAdded = isAdded;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<String> getQuestions() {
        return questions;
    }

    public void setQuestions(List<String> questions) {
        this.questions = questions;
    }

    public int getSelectedId() {
        return selectedId;
    }

    public void setSelectedId(int selectedId) {
        this.selectedId = selectedId;
    }
}

Ответы [ 7 ]

0 голосов
/ 05 марта 2019

Попробуйте переместить setOnCheckedChangeListener код в ViewHolder и обновите mCheckList здесь

priceGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
        mCheckList.get(getAdapterPosition()).setSelectedId(checkedId);
        Log.d(TAG, "onCheckedChanged: " + radioGroup.getCheckedRadioButtonId() + " " + i);
}});

Основная проблема в том, что вы не обновляете правильное состояние предметов.Когда вы щелкаете по переключателю, он обновляет только последний вызванный элемент onBindViewHolder, потому что checklistModel содержит только последнюю ссылку.Чтобы это исправить, вам всегда нужно обращаться к mainList внутри слушателей.

0 голосов
/ 05 марта 2019

Способ, которым работает просмотрщик утилит, заключается в том, что когда вы прокручиваете вниз или вверх, пока представление не становится невидимым, он сохраняет состояние, но когда вы прокручиваете вниз просмотр и повторение прокрутки вверх, он уничтожает строку и помещает в нее новую строку.position.so представление всей строки будет уничтожено.

Решение вопроса состоит в том, что вы добавляете другую переменную в список, который вы используете, и когда переключатель переключает состояние, вы сохраняете данные и продолжаете.как это происходит в вашем классе модели данных. И в Model Class вы определяете, какой список использует утилита восстановления.

Boolean is stateclicked;
int state position;

и в OnBindViewholder вы можете получить значение этих данных.Если значение равно нулю, то оно не щелкается, а если оно щелкается, тогда вы меняете логическое значение на да и помещаете значение состояния в целое число

0 голосов
/ 05 марта 2019

Хотя я не уверен, решит ли это вашу проблему или нет, но в качестве оптимизации также хорошая практика, вы должны прикреплять слушателей к onCreateViewHolder вместо onBindViewHolder, это предотвращает создание нескольких объектов.для слушателя.

Почему бы вам не переместить этот код внутри onCreateViewHolder

этого блока внутри держателя вида:

priceGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            checklistModel.setSelectedId(checkedId);
            Log.d(TAG, "onCheckedChanged: " + checkedId);
        }
    });
0 голосов
/ 05 марта 2019

Уникальным рабочим решением было установить RecyclerView для повторного использования в ViewHolder.

this.setIsRecyclable(false);
0 голосов
/ 04 марта 2019

Я вижу, что checklistModel объявляется вне метода onBindViewHolder:

checklistModel = mChecklists.get(position);

Таким образом, при прокрутке переменная класса checklistModel обновляется с помощью модели контрольного спискапоследняя сработавшая позиция onBindViewHolder.

Поэтому, когда вы нажимаете одну из переключателей, независимо от позиции, она обновляет модель контрольного списка последней сработавшей позиции onBindViewHolder.

Вы можете исправить это различными способами, одним из способов было бы объявить checklistModel внутри onBindViewHolder как окончательное:

final Checklist checklistModel = mChecklists.get(position);
0 голосов
/ 02 марта 2019

Как насчет следующего кода?

Адаптер:

Поскольку представление перерабатывается, я подумал, что уникальный идентификатор является ошибкой.

int id = (position+1)*100;

до

int id = 1;
0 голосов
/ 02 марта 2019

Сохраните отмеченный / непроверенный статус переключателя в вашей модели (т. Е. Ваши элементы в списке должны иметь поле для этого), когда происходит событие onClick.Когда вы связываете ViewHolder, убедитесь, что вы установили значение флажка на то, что вы сохранили в своей модели.

...