如何在自定义ArrayAdapter中引用每个视图?

时间:2017-05-21 05:51:41

标签: android

我对编程和Android开发都很陌生,所以请原谅我,如果我的基础知识还不是很精通的话。我在底部提供了我的代码。

如标题中所述,如何在我的自定义arrayadapter创建的视图中引用每个视图?这样我就可以访问arrayadapter中每个视图对象的变量。

实际上,我有两个问题需要实现。所以现在我正在尝试创建一个由科学测试组成的简单应用程序。我已设法将所有与CheckBox视图配对的问题(TextViews)显示到ListView布局中。我的想法是,当用户检查CheckBox时,它会存储一个真正的'某处的布尔值(可能在ArrayList中)。之后在分数汇总活动中,我将用户的答案与原始布尔值(问题的正确答案)进行比较,以检查是否为每个问题给出了正确的答案并返回分数。这样做是否明智?

  

TestActivity.java

package com.example.android.scienceknowledgetest;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ListView;

import java.util.ArrayList;

public class TestActivity extends AppCompatActivity {

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

        // ArrayList of all the questions and their boolean (answer) values
        ArrayList<Question> questions = new ArrayList<Question>();
        questions.add(new Question("Plants derive most of their dry mass from the air", true, ""));
        questions.add(new Question("Aluminium is the most common metal in the Earth's crust", true, ""));
        questions.add(new Question("Vitamin C has be shown to prevent colds", false, ""));
        questions.add(new Question("We lose most of our heat through our heads", false, ""));
        questions.add(new Question("Dogs are unable to digest chocolate", false, ""));
        questions.add(new Question("Apple pips contain cyanide", true, ""));
        questions.add(new Question("Cholesterol is a naturally-occurring toxic substance", false, ""));
        questions.add(new Question("When you're on a diet, you lose weight by oxidising fat to a gas and exhaling it", true, ""));
        questions.add(new Question("Human beings are unable to sense when the oxygen level of the air is low", true, ""));
        questions.add(new Question("Most of the Y chromosome is passed unchanged from father to son", true, ""));

        // Constructing a new TestAdapter instance
        TestAdapter adapter = new TestAdapter(this, questions);

        // Find the ListView to display the questions and check boxes
        ListView questions_checkbox_list = (ListView) findViewById(R.id.question_checkbox_list);
        // Display the questions and check boxes to the ListView questions_checkbox_list
        questions_checkbox_list.setAdapter(adapter);

        // Configuring the Button Submit
        Button submitAnswers = (Button) findViewById(R.id.submit_answers);
        submitAnswers.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent endTest = new Intent(TestActivity.this, TestSummary.class);
                startActivity(endTest);
            }
        });
    }
}
  

TestAdapter

package com.example.android.scienceknowledgetest;

import android.app.Activity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.ArrayList;

public class TestAdapter extends ArrayAdapter<Question> {

    // TestAdapter constructor
    public TestAdapter(Activity context, ArrayList<Question> questions) {
        super(context, 0, questions);
    }

    private View listItemsView;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Check if the current view is recycled, otherwise inflate new view
        listItemsView = convertView;
        if (listItemsView == null) {
            listItemsView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
        }

        // Find the current Question object and store in the variable currentQuestion
        Question currentQuestion = getItem(position);

        // Find the TextView texts of the Question and set the question
        TextView questionText = (TextView) listItemsView.findViewById(R.id.question_text);
        questionText.setText(currentQuestion.getmQuestion());

        // Find the CheckBox of the Question and set the boolean value
        CheckBox answerBool = (CheckBox) listItemsView.findViewById(R.id.answer_boolean);

        // Return the item as a view
        return listItemsView;
    }
}
  

Question.java

package com.example.android.scienceknowledgetest;

public class Question {

    // Declaring the question variable
    private String mQuestion;

    // Declaring the answer variable
    private boolean mAnswer;

    // Declaring the attempt variable
    private String mAttempt;

    // Getter method to request for the question
    public String getmQuestion() {
        return  mQuestion;
    }

    // Getter method to request for the boolean value of the answer
    public boolean getmAnswer() {
        return mAnswer;
    }

    // Question Constructor
    public Question(String question, boolean answer, String attempt) {
        mQuestion = question;
        mAnswer = answer;
        mAttempt = attempt;
    }
}
  

activity_test.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical">

    <ListView
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:id="@+id/question_checkbox_list" />

    <Button
        android:layout_weight="0"
        android:id="@+id/submit_answers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/submit_answers"
        android:textSize="16sp"
        android:layout_margin="16dp"
        android:layout_marginLeft="48dp"/>

</LinearLayout>
  

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <CheckBox
        android:id="@+id/answer_boolean"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/question_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="8dp"
        tools:text="When you're on a diet, you lose weight by oxidising fat to a gas and exhaling it"/>

</LinearLayout>

1 个答案:

答案 0 :(得分:0)

这里有你想要的东西。它都在适配器中。这是TestAdpater的代码: -

public class TestAdapter extends ArrayAdapter<Question> {

    Context passedcontext;

    // TestAdapter constructor
    public TestAdapter(Activity context, ArrayList<Question> questions) {
        super(context, 0, questions);
        passedcontext = context;
    }

    private View listItemsView;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Check if the current view is recycled, otherwise inflate new view
        listItemsView = convertView;
        if (listItemsView == null) {
            listItemsView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
        }

        // Find the current Question object and store in the variable currentQuestion
        Question currentQuestion = getItem(position);

        // Find the TextView texts of the Question and set the question
        TextView questionText = (TextView) listItemsView.findViewById(R.id.question_text);
        questionText.setText(currentQuestion.getmQuestion());

        // Find the CheckBox of the Question and set the boolean value
        CheckBox answerBool = (CheckBox) listItemsView.findViewById(R.id.answer_boolean);
        answerBool.setTag(position);
        answerBool.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                detectCheckBoxChanged(buttonView, isChecked);

            }
        });

        // Return the item as a view
        return listItemsView;
    }

    public void detectCheckBoxChanged(CompoundButton buttonview, boolean ischecked) {
        Toast.makeText(passedcontext,
                "CheckBox " +
                        buttonview.getTag().toString() +
                        " Changed to " + Boolean.toString(ischecked),
                Toast.LENGTH_SHORT).show();
    }
}

第一个变化是增加了一行: -

Context passedcontext;

这将保存调用活动的上下文(下一个新的代码行)。

第二个更改是添加了一行来设置带有调用活动的上下文的passcontext,这在TestAdapter的构造函数中完成: -

passedcontext = context;

下一个更改是使用位置设置CheckBoxes的标记,以便您可以确定哪个CheckBox已触发监听器。在您getView方法中确定了CheckBox的ID后,会立即(或不久之后)出现这种情况,该方法可以方便地传递位置。: -

answerBool.setTag(position);

为了按顺序执行操作并且可能简化代码,将一个新的类方法添加到类中以处理CheckBox Changed事件(在这种情况下发出一个Toast,详细说明单击了哪个CheckBox及其状态)。注意它是使用这个Toast为什么我们得到了调用活动的上下文,因为Toast需要一个上下文来显示: -

    public void detectCheckBoxChanged(CompoundButton buttonview, boolean ischecked) {
        Toast.makeText(passedcontext,
                "CheckBox " +
                        buttonview.getTag().toString() +
                        " Changed to " + Boolean.toString(ischecked),
                Toast.LENGTH_SHORT).show();
    }

最后一段代码设置并包含要更改的CheckBox的侦听器。您可以将上面的代码合并到侦听器中,而不是调用新的detectCheckBoxChanged方法。此代码添加在getView方法中,并且在确定了CheckBox的ID之后需要(至少是设置): -

        answerBool.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                detectCheckBoxChanged(buttonView, isChecked);

            }
        });

您可以更改 detectCheckBoxChanged 方法,以包含以下内容: -

    int position = Integer.parseInt(buttonview.getTag().toString());
    TestActivity.handleCheckBoxChanged(position, isChecked);

在这种情况下,将调用TestActivity活动(调用活动)中的handleCheckBoxChanged方法,例如,

    public static void handleCheckBoxChanged(int position, boolean ischecked) {
        // handle the change here using the position
        Log.d("CHKBOXHIT",
                "Checkbox " +
                        Integer.toString(position) +
                        " was hit it is now "
                        + Boolean.toString(ischecked)
        );
    }

以下更改可能是绕过&#34;未回答&#34;问题我评论过。

1)将一个int数组作为类变量添加到TestActivity中(即在公共类TestAdapter扩展ArrayAdapter {&#39;之后),例如。

    static int[] answers;

2)设置answers数组并将元素初始化为无法回答的值,此代码遵循问题ArrayList的设置。 e.g。

    answers = new int[questions.size()];
    for (int i = 0; i < answers.length; i++ ) {
        answers[i] = -1;
    }

3)添加一个新方法,当单击一个传递索引和状态的答案时将调用该方法。

public static void setAnswer(int index, boolean answer) {
    answers[index] = 0;
    if (answer) {
        answers[index] = 1;
    }
}

4)将以下行添加到TestAdapter类中的detectCheckBoxChanged方法: -

    TestActivity.setAnswer(position, ischecked);

5)要测试它,请将TestActivity中的submitAnswers onClick侦听器更改为: -

    submitAnswers.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //Intent endTest = new Intent(ScienceKnowledgeTest.this, ScienceKnowledgeTest.class);
            //startActivity(endTest);
            for (int i =0; i < answers.length; i++) {
                switch (answers[i]) {
                    case -1:
                        Log.d("RESULTS", "Question "
                                + Integer.toString(i + 1) +
                                " was not answered."
                        );
                        break;
                    case 0:
                        Log.d("RESULTS", "Question " +
                                Integer.toString(i + 1) +
                                " was answered as False"
                        );
                        break;
                    case 1:
                        Log.d("RESULTS", "Question " +
                                Integer.toString(i + 1) +
                                " was answered as True"
                        );
                        break;
                    default:
                        Log.d("RESULTS", "Well that's unusual something appears to be wrong!!!");
                        break;
                }

            }
        }
    });

但是,这有一个问题,即选择一个错误的答案需要2次点击才能将复选框设置为true,然后再设置为false。两个复选框一个用于true,一个用于false将更清晰。