通过循环为按钮分配onClickListeners - Android

时间:2013-02-15 16:12:48

标签: java android button onclicklistener

我知道如何通过长期不优雅的方式完成这项任务,但我想缩短它并使其更优雅。下面我展示了我可以做的非优雅的方式以及我想如何优雅地做到这一点。优雅的方式不是编译。我评论了错误的位置和错误。

任何代码结构帮助表示赞赏!提前谢谢。

Results.java

public class Results extends Activity {
int x = -1;

Button q1details, q2details, q3details, q4details, q5details, q6details, q7details, q8details, q9details, q10details;

final Context context = this;

@Override
public void onCreate(Bundle savedInstanceState) {

    q1details = (Button)findViewById(R.id.q1details);
    q2details = (Button)findViewById(R.id.q2details);
    q3details = (Button)findViewById(R.id.q3details);
    q4details = (Button)findViewById(R.id.q4details);
    q5details = (Button)findViewById(R.id.q5details);
    q6details = (Button)findViewById(R.id.q6details);
    q7details = (Button)findViewById(R.id.q7details);
    q8details = (Button)findViewById(R.id.q8details);
    q9details = (Button)findViewById(R.id.q9details);
    q10details = (Button)findViewById(R.id.q10details);

    buttonList.add(q1details); buttonList.add(q2details); buttonList.add(q3details); buttonList.add(q4details); buttonList.add(q5details); buttonList.add(q6details); buttonList.add(q7details); buttonList.add(q8details); buttonList.add(q9details); buttonList.add(q10details);

    for(int i = 0; i < buttonList.size(); i++) {
        buttonList.get(i).setText("Question Details");
        buttonList.get(i).setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                x = i;  //ERROR:  "Cannot refer to a non-final variable  i inside an inner class defined in a different method."  But I cannot put the i as Final in a for-loop.
                displayDetails();
            }
        });
    }

/*      q1details.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            x = 0;
            displayDetails();
        }
    });
            //I could do 10 of these to accomplish the task but its non-elegant...
*/

public void displayDetails() {

    final Dialog dialog = new Dialog(context);
    dialog.setContentView(R.layout.questiondetails);
    dialog.setTitle("Question " + (x + 1) + " Details");

    ImageView image = (ImageView)dialog.findViewById(R.id.image);
    TextView correctness = (TextView)dialog.findViewById(R.id.correctness);
    TextView questionHeader = (TextView)dialog.findViewById(R.id.questionHeader);
    TextView question = (TextView)dialog.findViewById(R.id.question);
    TextView selectedAnswerHeader = (TextView)dialog.findViewById(R.id.selectedAnswerHeader);
    TextView selectedAnswer = (TextView)dialog.findViewById(R.id.selectedAnswer);
    TextView correctAnswerHeader = (TextView)dialog.findViewById(R.id.correctAnswerHeader);
    TextView correctAnswer = (TextView)dialog.findViewById(R.id.correctAnswer);
    TextView points = (TextView)dialog.findViewById(R.id.points);
    TextView verseHeader = (TextView)dialog.findViewById(R.id.verseHeader);
    TextView verse = (TextView)dialog.findViewById(R.id.verse);
    Button close = (Button)dialog.findViewById(R.id.close);

    if(qs.get(x).getSelectedAnswer() == qs.get(x).getCorrectAnswer()) {
        image.setBackgroundResource(R.drawable.green_check_mark);
        correctness.setText("CORRECT!");
        correctness.setTextColor(Color.GREEN);
    } else {
        image.setBackgroundResource(R.drawable.red_x);
        correctness.setText("INCORRECT!");
        correctness.setTextColor(Color.RED);
    }

    String a = "<u>QUESTION</u>";
    questionHeader.setText(Html.fromHtml(a));
    question.setText(qs.get(0).getQuery());

    String b = "<u>ANSWER YOU SELECTED</u>";
    selectedAnswerHeader.setText(Html.fromHtml(b));
    selectedAnswer.setText("" + qs.get(0).getStringSelectedAnswer());

    String c = "<u>CORRECT ANSWER</u>";
    correctAnswerHeader.setText(Html.fromHtml(c));
    correctAnswer.setText("" + qs.get(0).getStringCorrectAnswer());

    points.setText("You received " + QuestionView.getPointsPerQuestion().get(x) + " out of a possible 100 points.");

    String d = "<u>PROVE THE ANSWER IN YOUR BIBLE</u>";
    verseHeader.setText(Html.fromHtml(d));
    verse.setText(qs.get(0).getVerse());        

    close.setText("Close");

    close.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            dialog.dismiss();
        }
    });
    dialog.show();
}

3 个答案:

答案 0 :(得分:6)

匿名类的正外部范围中声明的最终引用可供该匿名类访问。 (Java的封闭风味):

for(int i = 0; i < buttonList.size(); i++) {
    Button button = buttonList.get(i);
    button.setText("Question Details");

    final int j = i;

    button.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            x = j;
            displayDetails();
        }
    });
}

答案 1 :(得分:2)

按下按钮时,onClick()内的代码将会运行,而不是在循环中运行...所以,即使你以某种方式使i成为最终版,它也不会保留你期望的值

但是,您可以使用通用的setTag()getTag()方法来存储i
类似的东西:

for(int i = 0; i < buttonList.size(); i++) {
    Button button = buttonList.get(i);
    button.setTag(i);
    button.setText("Question Details");
    button.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            x = (Integer) arg0.getTag();
            displayDetails();
        }
    });
}

答案 2 :(得分:0)

您无法像这样在匿名函数中引用变量。有3种方法可以解决这个问题。

1)在视图上使用setTag和getTag,用索引号

标记它

2)不要使用匿名类。使它成为在函数外部定义的私有类(但在activity类中),并使其通过其构造函数获取索引。

3)在每次点击步骤中按下按钮列表,找到等于传入视图的索引。

我认为2号是最干净的,但它们中的任何一个都可以工作。