Урок 14. Проверяем ответ (setOnClickListener)

В этом уроке мы научимся определять верно или неверное дал ответ наш пользователь и на основании этого будем выводить всплывающее сообщение. Наши познания в Java улучшились и давайте закрепим это на практике. Подробные объяснения кода будут ближе к концу урока. А пока следуем данному руководству:

 

  • Откройте файл GameActivity.java в окне редактора кода;
  • Теперь нужно добавить возможность “прослушивать” наше приложение нажатия пользователя по кнопкам так же, как мы сделали это в MainActivity. Введите следующий код сразу же после последней строки кода в методе onCreate, но до закрывающейся фигурной скобки “}”:
    buttonObjectChoice1.setOnClickListener(this);
    buttonObjectChoice2.setOnClickListener(this);
    buttonObjectChoice3.setOnClickListener(this);
  • Ключевое слово this” пока подчеркнуто красным, что указывает нам на ошибку. Опять же, мы должны внести изменения в наш код, чтобы использовать интерфейс (специальный элемент кода), который позволяет добавлять такие функции, как “прослушивание” нажатий кнопки. Измените строку следующим образом. Если появится запрос на импорт другого класса, нажмите кнопку ОК. Эту строку нужно изменить:
    public class GameActivity extends AppCompatActivity {

    Вот так:

    public class GameActivity extends AppCompatActivity implements View.OnClickListener{
  • Но теперь у нас полностью подчеркнута красным эта строка, что опять указывает нам на ошибку в коде. Ничего страшного, она там и должна быть. Мы уже упоминали, что при добавлении View.OnClickListener, мы реализуем интерфейс. Мы можем думать об этом, как класс, который мы можем использовать, но с некоторыми условиями. Одно из правил интерфейса OnClickListener гласит, что мы должны реализовать один из методов, как вы помните. Давайте добавим метод onClick (если красной лампочки у вас не видно, то поставьте каретку редактирования в строку и нажмите комбинацию клавиш Alt+Enter):

implement methods

apply implementation

  • В данном случае всю работу за нас выполнила Android Studio, но вместо этого мы могли сами добавить этот код сразу же за закрывающейся фигурной скобкой метода onCreate, но перед закрывающейся фигурной скобкой нашего GameActivity класса:
    @Override
    public void onClick(View view) {
    
    }

Обратите внимание, что тело метода пустое (то, что находится между фигурными скобками), но этого вполне достаточно для того, чтобы ошибка исчезла.

  • Теперь можем поместить в пустое тело метода onClick код, чтобы наши кнопки начали что-нибудь делать. Нам нужно провести различие между тремя возможными кнопками, которые можно нажать. Мы сделаем это с помощью оператора Switch, который обсуждали ранее. Посмотрите case’ы, они должны выглядеть знакомыми. Ниже приведен код, использующий оператор Switch:
    switch (view.getId()) {
            case R.id.buttonChoice1:
                //код для кнопки 1
                break;
            case R.id.buttonChoice2:
                //код для кнопки 2
                break;
            case R.id.buttonChoice3:
                //код для кнопки 3
                break;
        }
  • Каждый case обрабатывает свою кнопку. В каждый case кнопки мы должны ввести следующий функционал: получить значение, хранящееся в кнопке, на которую нажал пользователь и проверить соответствует ли значение этой переменной значению переменной correctAnswer. Если значения совпадают, то пользователю всплывает сообщение о верном ответе, если нет – то всплывает сообщение о неверном ответе. Однако, у нас еще остаётся одна проблема, которую нам надо решить. Дело в том, что метод onClick и метод onCreate, в котором мы объявили и инициализировали объекты Button разделены между собой – проще говоря метод onClick не видит наши кнопки (это отдельная тема в программировании именуется как “глобальные и локальные переменные”, попозже и с этим разберёмся подробнее). Нам нужно сделать так, чтобы все переменные, которые мы запланировали использовать в методе onClick стали доступными для этого метода. И для этого нам всего лишь необходимо переместить объявление этих переменных из метода onCreate сразу же после “{” нашего класса GameActivity. Это означает, что эти переменные становятся переменными класса GameActivity и могут быть видны в любом месте GameActivity. Объявите переменные следующим образом:
    int correctAnswer;
    Button buttonObjectChoice1;
    Button buttonObjectChoice2;
    Button buttonObjectChoice3;
  • Теперь необходимо изменить инициализацию этих переменных внутри метода onCreate. Требуемые для изменения строки выделены жирным, остальное показано в качестве контекста:
    int partA = 9;
    int partB = 9;
    correctAnswer = partA * partB;
    int wrongAnswer1 = correctAnswer - 1;
    int wrongAnswer2 = correctAnswer + 1;

    и

    TextView textObjectPartA =  (TextView)findViewById(R.id.textPartA);
    TextView textObjectPartB =  (TextView)findViewById(R.id.textPartB);
    buttonObjectChoice1 =  (Button)findViewById(R.id.buttonChoice1);
    buttonObjectChoice2 =  (Button)findViewById(R.id.buttonChoice2);
    buttonObjectChoice3 =  (Button)findViewById(R.id.buttonChoice3);
  • Вот начало метода onClick и первый case. Не забудьте импортировать недостающие классы:
    @Override
    public void onClick(View view) {
    
        //объявим новую переменную типа int, которую будем использовать в каждом case
        int answerGiven=0;
    
        switch (view.getId()) {
            case R.id.buttonChoice1:
                //присваиваем переменной answerGiven значение, содержащееся в buttonObjectChoice1
                //это значение мы сами поместили туда ранее
                answerGiven = Integer.parseInt("" + buttonObjectChoice1.getText());
                //получен верный овтет?
                if(answerGiven==correctAnswer) {//да - это верный ответ
                    Toast.makeText(getApplicationContext(),
                            "Well done!",
                            Toast.LENGTH_LONG).show();
                }else{//нет, неверно!
                    Toast.makeText(getApplicationContext(),"Sorry that's wrong", Toast.LENGTH_LONG).show();
                }
                break;
  • Ниже приведены остальные объявления наших case’ов, которые выполняют те же функции, что и предыдущий за исключением того, что обрабатывают разные кнопки. Введите этот код сразу же после последней строчки из предыдущего шага:
    case R.id.buttonChoice2:
        //то же самое, что и предыдущий case, только используем следующую кнопку
        answerGiven = Integer.parseInt("" + buttonObjectChoice2.getText());
        if(answerGiven==correctAnswer) {
            Toast.makeText(getApplicationContext(), "Well done!", Toast.LENGTH_LONG).show();
        }else{
            Toast.makeText(getApplicationContext(),"Sorry that's wrong", Toast.LENGTH_LONG).show();
        }
        break;
    
    case R.id.buttonChoice3:
        //то же самое, что и предыдущий case, только используем следующую кнопку
        answerGiven = Integer.parseInt("" + buttonObjectChoice3.getText());
        if(answerGiven==correctAnswer) {
            Toast.makeText(getApplicationContext(), "Well  done!", Toast.LENGTH_LONG).show();
        }else{
            Toast.makeText(getApplicationContext(),"Sorry  that's wrong", Toast.LENGTH_LONG).show();
        }
        break;
  • Запустите программу и проверьте её работоспособность, после чего мы пройдёмся подробнее по коду и этой странной штуке Toast. Вот скриншот того, что у нас получилось:

android studio app

Что мы сделали:

Шаг 1-6 — мы настроили обработку для наших кнопок с несколькими вариантами выбора, включая добавление возможности “прослушивания” кликов с помощью метода onClick и блока switch для обработки решений в зависимости от нажатой кнопки.

Шаг 7-8 – мы изменили наш код таким образом, чтобы необходимые нам переменные были доступны в методе onClick, сделав их переменными нашего GameActivity класса (глобальные и локальные переменные – поговорим о них позже).

Шаги 9 и 10 – мы реализовали код, который фактически выполняет работу в Switch блоке в методе onClick. Посмотрим построчно на код, который будет выполняться при нажатии кнопки button1:

case R.id.buttonChoice1:

Этот case будет достигнут при нажатии пользователем кнопки с id buttonChoice1. Следующая строка:

answerGiven = Integer.parseInt("" + buttonObjectChoice1.getText());

 
В этой строке мы получаем значение, которое хранится в кнопке, используя следующие методы. Сначала getText извлекает строку с числом, хранящееся в кнопке. Затем Integer.parseInt конвертирует это строку в целочисленное значение. После – это значение присваивается переменной answerGiven. Следующий фрагмент кода:

if(answerGiven==correctAnswer) {//да - это верный ответ
        Toast.makeText(getApplicationContext(), "Well done!", Toast.LENGTH_LONG).show();
    }else{//нет, неверно!
        Toast.makeText(getApplicationContext(),"Sorry that's wrong", Toast.LENGTH_LONG).show();
    }

Оператор if выполняет проверку условия, а именно – сравнивает значение переменной, хранящейся в answerGiven и значение переменной, хранящейся в correctAnswer, используя знакомый нам оператор сравнения “==”. Если оба эти значения совпадают, то используем метод makeText объекта класса Toast для отображения на экране поздравительного сообщения. Если эти значения не совпадают, то делаем тоже самое, только для отображения сообщения о неверном ответе. И в конце мы пишем:

break;

Делаем это для того, чтобы выйти из оператора Switch. В противном случае (если бы мы не использовали ключевое слово break) программа исполнила бы следующую строку, а этого нам не надо. Повторяем код для оставшихся двух кнопок с соответствующими изменениями имён переменных этих кнопок. Если что-то не получается, сверьте свой код с моим, который вы можете увидеть, скачав исходники в конце урока.

Если есть вопросы – добро пожаловать в комментарии. В следующих уроках мы продолжим работу над нашим приложением и добавим такие функции, как случайные вопросы различной сложности.

Чтобы мы смогли это сделать, нам опять придётся погрузиться в теорию о Java.

Скачать исходники