Как использовать Radiogroup с 4 разными переключателями в ArrayAdapter

У меня есть настраиваемый адаптер списка, у которого есть вопрос в текстовом представлении и четыре варианта ответа в радиокнопках. Все радиокнопки объединены в радиогруппу. Проблема в том, что я не могу отслеживать проверенные кнопки. При прокрутке кнопки проверяются случайным образом. Как я могу сохранить переключатели, которые проверяются для определенного


открытый класс MCQAdapter расширяет ArrayAdapter {

public MCQAdapter(Activity context, ArrayList<MCQ> mcq) {
    super(context, 0, mcq);
}

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View listItemView = convertView;

    if (listItemView == null) {
        listItemView = LayoutInflater.from(getContext()).inflate(R.layout.activity_mcqlist, parent, false);
    }


    final MCQ currentContent = (MCQ) getItem(position);
    TextView content = (TextView) listItemView.findViewById(R.id.Question_Block);
    content.setText(currentContent.getQuestion());

    RadioGroup rg = (RadioGroup) listItemView.findViewById(R.id.Radio_Group);

    final RadioButton rb1 = (RadioButton) listItemView.findViewById(R.id.Option1_Block);
    rb1.setText(currentContent.getOptionA());

    final RadioButton rb2 = (RadioButton) listItemView.findViewById(R.id.Option2_Block);
    rb2.setText(currentContent.getOptionB());

    final RadioButton rb3 = (RadioButton) listItemView.findViewById(R.id.Option3_Block);
    rb3.setText(currentContent.getOptionC());

    final RadioButton rb4 = (RadioButton) listItemView.findViewById(R.id.Option4_Block);
    rb4.setText(currentContent.getOptionD());

    return listItemView;

}

}

public class MCQ {

String question,optionA,optionB,optionC,optionD,answer,userAnswer;

public MCQ(String quest,String a,String b,String c, String d,String ans){

    question = quest;
    optionA = a;
    optionB = b;
    optionC = c;
    optionD = d;
    answer = ans;

}

public String getQuestion(){
    return question;
}

public String getOptionA() {
    return optionA;
}

public String getOptionB() {
    return optionB;
}

public String getOptionC() {
    return optionC;
}

public String getOptionD() {
    return optionD;
}

public String getAnswer() {
    return answer;
}

public String getUserAnswer() {
    return userAnswer;
}

public void setUserAnswer(String userAnswer) {
    this.userAnswer = userAnswer;
}

}

public class PropertiesOfConstructionMaterail extends AppCompatActivity {

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

    final ArrayList<MCQ> mcq = new ArrayList<MCQ>();

    //Creating Different Instance Of MCQ to genarte various questions for Properties of Consrtuction Material
    mcq.add(new MCQ("The property of material by which it can be beaten or rolled into thin plates, is called ?",
            "Malleability","Ductility","Plasticity","Elasticity","Malleability"));
    mcq.add(new MCQ("The property by which a body returns to its original shape after removal of the force, is called ?",
            "Plasticity","Elasticity","Ductility","Malleability","Elasticity"));
    mcq.add(new MCQ("The property of a material by which it can be drawn into smaller section due to tension, is called ?"
            ,"Plasticity","Ductility","Elasticity","Malleability","Ductility")); 

MCQAdapter adapter = new MCQAdapter(this,mcq);

    ListView listView = (ListView) findViewById(R.id.list);
    listView.setAdapter(adapter);
}

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_mcqlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.silen.civilengineeringmcq.MCQList"
android:orientation="vertical">

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/Question_Block"
    android:textSize="18dp"
    android:textStyle="bold"/>

<RadioGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/Radio_Group">

    <RadioButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Option1_Block"
        android:checked="false"/>

    <RadioButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Option2_Block"
        android:checked="false"/>

    <RadioButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Option3_Block"
        android:checked="false"/>

    <RadioButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Option4_Block"
        android:checked="false"/>

</RadioGroup>


person Nikhil Rauniyar    schedule 23.10.2016    source источник


Ответы (1)


Вы должны создать оболочку вокруг вашего класса PoJo (MCQ), назовите ее ViewModel, которая хранит текущее состояние просмотра внутри адаптера. В вашем случае это состояние - это состояние переключателей.

Это будет выглядеть так:

class ViewModel extends MCQ {
    MCQ mcq;

    int radioButtonSelectedId;

    public ViewModel(MCQ mcq) {
        this.mcq = mcq;
        this.radioButtonSelectedId = R.id.Option1_Block;
    }

    public void setRadioButtonSelectedId(int id) {
        this.id = id;
    }

    public int getRadioButtonSelectedId() {
        return id;
    }

    //delegates to mcq getter/setter methods
}

Ваш getView метод:

public View getView(int position, View convertView, ViewGroup parent) {
//your logic above
    radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                viewModel.setRadioButtonSelectedId(checkedId);
            }
        });

    //same for other radio buttons
    rb1.setChecked(viewModel.getRadioButtonSelectedId() == R.id.Option1_Block);
//your logic below
}

Итак, как я упоминал выше, ваш список массивов внутри адаптера будет содержать ViewModels оболочки, а не MCQ классы напрямую

final ArrayList<ViewModel> mcqList = new ArrayList<>();
MCQ mcq = new MCQ("The property of material by which it can be beaten or rolled into thin plates, is called ?",
        "Malleability","Ductility","Plasticity","Elasticity","Malleability")
mcqList.add(new ViewModel(mcq));

Я думаю, тебе стоит выбрать вариант

person Beloo    schedule 23.10.2016
comment
Я все еще не могу заставить код работать. Я сделал, как вы меня просили, но когда я проверяю опцию для первого радиобокса и прокручиваю вниз, первоначальная проверка исчезает и передается в какую-то другую радиогруппу. - person Nikhil Rauniyar; 23.10.2016
comment
@NikhilRauniyar в представлениях элементов ListView перерабатывается представлением списка, то есть представление создается один раз, а затем передается как следующий элемент, когда предыдущий подключенный элемент становится невидимым. Поэтому, если вы не сбросили состояние должным образом, в getView представлении будут представлены некоторые из предыдущих элементов. Итак, как я предлагал, вы должны выполнить это rb1.setChecked(viewModel.getRadioButtonSelectedId() == R.id.Option1_Block) для каждой из ваших радиокнопок (rb1,2,3,4), а также запустить вашу ViewModel с первым идентификатором радиокнопки. См. Отредактированный ответ - person Beloo; 23.10.2016
comment
Не могли бы вы привести образец кода или пример, который похож на мою проблему, потому что даже после того, как я реализовал ваш метод, у меня все еще есть та же проблема. Я застрял в этом вопросе больше суток - person Nikhil Rauniyar; 24.10.2016