Assigning onClickListeners for buttons through a loop - Android
android, button, java, onclicklistener
Solution
Final references declared in the just outer scope of an anonymous class are accessible to that anonymous class. (Java's flavor of closures):
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();
}
});
}
Problem
I know how to accomplish this task through a long non-elegant way but I want to shorten it down and make it more elegant. Below I show what I could do the non-elegant way and how I want to do it elegantly. The elegant way is not compiling. I commented in where and what the error is. Any code structure help is appreciated! Thank you in advance. 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(); } ```