In fact use a scrollable view within another scrollable view behind problems.
Maybe that's why Android provides the ExpandableListView component that more is not what a ListView whose items are lists.
So one solution to your problem would be to use one.
Define two classes, one to represent the question and another to represent the answer:
Question.java
Responsible for saving the question text, the answers, the correct answer and the selected answer.
public class Question {
private final String questionText;
private ArrayList<Answer> answers;
private int selectedAnswer = -1;
private int correctAnswer = -1;
public Question(String text) {
this.questionText = text;
answers = new ArrayList<>();
}
public boolean isCorrectlyAnswered(){
return correctAnswer == getSelectedAnswer();
}
public int getSelectedAnswer() {
return selectedAnswer;
}
public void setSelectedAnswer(int selectedAnswer) {
this.selectedAnswer = selectedAnswer;
}
public void setCorrectAnswer(int correctAnswer) {
if(answers.size() <= correctAnswer){
throw new IllegalArgumentException();
}
this.correctAnswer = correctAnswer;
}
public void addAnswer(String text){
answers.add(new Answer(text));
}
public String getText(){
return questionText;
}
public ArrayList<Answer> getAnswers(){
return answers;
}
}
Answer.java
Responsible for saving the text of the response.
public class Answer {
private final String answerText;
public Answer(String text){
this.answerText = text;
}
public String getText() {
return answerText;
}
}
The way to handle an ExpandableListView is similar to that of a ListView . The difference is that in addition to an Adpater and a view for items ( group ) it is necessary to define a view for the sub-items ( children ).
question_row.xml View for the questions, represents each of the ExpandableListView groups.
Contains the question text and a sign to indicate if the question was answered correctly.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="75dp"
card_view:cardCornerRadius="4dp">
<TextView
android:id="@+id/questionText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="questionText"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/correctMark"
android:layout_gravity="right"
android:clickable="false"
android:focusable="false"
android:checked="true"
android:visibility="gone"/>
</android.support.v7.widget.CardView>
</LinearLayout>
answer_row.xml View for responses, represents each of the sub items within each ExpandableListView group.
Contains a RadioButton with the response text.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New RadioButton"
android:id="@+id/answerText"
android:clickable="false"
android:focusable="false"/>
</LinearLayout>
ExpandListAdapter.java
Responsible for bridging the data and the ExpandableListView
public class ExpandListAdapter extends BaseExpandableListAdapter {
private final LayoutInflater inflater;;
private ArrayList<Question> questions;
public ExpandListAdapter(Context context, ArrayList<Question> questions){
inflater = LayoutInflater.from(context);
this.questions = questions;
}
@Override
public int getGroupCount() {
return questions.size();
}
@Override
public int getChildrenCount(int groupPosition) {
ArrayList<Answer> answers = questions.get(groupPosition).getAnswers();
if(answers == null){
return 0;
}
return questions.get(groupPosition).getAnswers().size();
}
@Override
public Object getGroup(int groupPosition) {
return questions.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return questions.get(groupPosition).getAnswers().get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null)
{
row = inflater.inflate(R.layout.question_row, parent, false);
holder = new ViewHolder();
holder.addView(row.findViewById(R.id.questionText))
.addView(row.findViewById(R.id.correctMark));
row.setTag(holder);
}else{
holder = (ViewHolder) row.getTag();
}
TextView questionText = (TextView) holder.getView(R.id.questionText);
CheckBox correctMark = (CheckBox) holder.getView(R.id.correctMark);
Question question = questions.get(groupPosition);
if(question.isCorrectlyAnswered()) {
correctMark.setVisibility(View.VISIBLE);
}else {
correctMark.setVisibility(View.GONE);
}
questionText.setText(question.getText());
return row;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null)
{
row = inflater.inflate(R.layout.answer_row, parent, false);
holder = new ViewHolder();
holder.addView(row.findViewById(R.id.answerText));
row.setTag(holder);
}else{
holder = (ViewHolder) row.getTag();
}
RadioButton answerText = (RadioButton) holder.getView(R.id.answerText);
if(questions.get(groupPosition).getSelectedAnswer() == childPosition){
answerText.setChecked(true);
}else{
answerText.setChecked(false);
}
answerText.setText(questions.get(groupPosition).getAnswers().get(childPosition).getText());
return row;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
static class ViewHolder
{
private HashMap<Integer, View> storedViews = new HashMap<Integer, View>();
public ViewHolder addView(View view)
{
int id = view.getId();
storedViews.put(id, view);
return this;
}
public View getView(int id)
{
return storedViews.get(id);
}
}
}
Only Activity is missing to display the list of questions and answers.
activity_main-xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/textView"
android:text="Questionário"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="32dp"/>
<ExpandableListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/expandableListView"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
MainActivity.java
Public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Obtém a referência da ExpandableListView
ExpandableListView expListView = (ExpandableListView) findViewById(R.id.expandableListView);
//Obtém a lista de perguntas a ser apresentada
final ArrayList<Question> questions = getQuestions();
//Cria uma instância do adapter e atribui-o à ExpandableListView
expListView.setAdapter(new ExpandListAdapter(this, questions));
//Define um listener para tratar a selecção das respostas
expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
//Indica que esta resposta foi seleccionada
questions.get(groupPosition).setSelectedAnswer(childPosition);
//Obtém a referência do adapter
ExpandListAdapter adapter = (ExpandListAdapter) parent.getExpandableListAdapter();
//Notifica o adapter da selecção para que ela seja representada visualmente
adapter.notifyDataSetChanged();
return true;
}
});
}
//Preenche um ArrayList com 10 perguntas e respectivas respostas
private ArrayList<Question> getQuestions() {
ArrayList<Question> questions = new ArrayList<>();
Question question;
int totalAnswers;
Random rnd = new Random();
for (int i = 1; i <= 10; i++){
question = new Question("Question - " + i);
//As perguntas pares têm 3 respostas as impar 5
if(i%2 == 0){
totalAnswers = 3;
}else{
totalAnswers = 5;
}
for (int j = 1; j <= totalAnswers; j++){
question.addAnswer("Answer - " + j + " to question - " + i);
}
//Atribui aleatóriamente a resposta correcta
question.setCorrectAnswer(rnd.nextInt(totalAnswers));
questions.add(question);
}
return questions;
}
}
Just adapt to your liking.
GitHubGist