В этом уроке мы:

- научимся использовать один обработчик для нескольких View-элементов
- научим Activity выступать в качестве обработчика

Создадим проект:
Project name: P0101_Listener
Build Target: Android 2.3.3
Application name: Listener
Package name: ru.startandroid.develop.listener
Create Activity: MainActivity


Будем работать с теми же View, что и в предыдущем уроке. Код для main.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="horizontal">
    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_margin="30dp">
        <TextView
            android:layout_width="wrap_content"
            android:text="TextView"
            android:layout_height="wrap_content"
            android:id="@+id/tvOut"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="50dp">
        </TextView>
        <Button
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:id="@+id/btnOk"
            android:text="OK"
            android:layout_width="100dp">
        </Button>
        <Button
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:id="@+id/btnCancel"
            android:text="Cancel"
            android:layout_width="100dp">
        </Button>
    </LinearLayout>
</LinearLayout>

 

Один обработчик для двух кнопок

Итак, у нас есть TextView с текстом и две кнопки. Как и на прошлом уроке, мы сделаем так, чтобы по нажатию кнопки менялось содержимое TextView. По нажатию кнопки OK – будем выводить текст: «Нажата кнопка ОК», по нажатию Cancel – «Нажата кнопка Cancel». Но сейчас мы сделаем это с помощью одного обработчика, который будет обрабатывать нажатия для обеих кнопок.

Напомню механизм обработки событий на примере нажатия кнопки. Сама кнопка обрабатывать нажатия не умеет, ей нужен обработчик (listener), который присваивается с помощью метода setOnClickListener. Когда на кнопку нажимают, обработчик реагирует и выполняет код из метода onClick.

Соответственно для реализации необходимо выполнить следующие шаги:
- создаем обработчик
- заполняем метод onClick
- присваиваем обработчик кнопке

В нашем случае мы будем присваивать один обработчик обеим кнопкам, а внутри обработчика надо будет определять, какая именно кнопка была нажата.

Подготовим объекты и создадим обработчик:

public class MainActivity extends Activity {
 
   TextView tvOut;
   Button btnOk;
   Button btnCancel;
 
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
 
     // найдем View-элементы
     tvOut = (TextView) findViewById(R.id.tvOut);
     btnOk = (Button) findViewById(R.id.btnOk);
     btnCancel = (Button) findViewById(R.id.btnCancel);
 
     // создание обработчика
     OnClickListener oclBtn = new OnClickListener() {
       @Override
       public void onClick(View v) {
         // TODO Auto-generated method stub
 
       }
     };
 
   }
 }

 

Давайте заполнять метод onClick. На вход ему подается объект класса View, это как раз то, что нам нужно. Это View, на которой произошло нажатие, и, которая вызвала обработчик. Т.е. в нашем случае это будет либо кнопка OK либо Cancel. Нам осталось узнать ID этой View и сравнить его с нашими R.id.btnOk и R.id.btnCancel, чтобы определить какая именно это кнопка. Чтобы получить ID какой-либо View, используется метод getId. Для перебора результатов используем java-оператор switch.

Реализация метода onClick:

      public void onClick(View v) {
         // по id определеяем кнопку, вызвавшую этот обработчик
         switch (v.getId()) {
         case R.id.btnOk:
           // кнопка ОК
           tvOut.setText("Нажата кнопка ОК");
           break;
         case R.id.btnCancel:
           // кнопка Cancel
           tvOut.setText("Нажата кнопка Cancel");
           break;
         }
       }

 

Если сейчас запустить приложение и проверить, то ничего не произойдет. Обработчик то мы создали, но не присвоили его кнопкам. Обеим кнопкам присваиваем один и тот же обработчик:

    btnOk.setOnClickListener(oclBtn);
    btnCancel.setOnClickListener(oclBtn);

 

 Вот теперь можем запускать и проверять, все должно работать.

Как вы понимаете, один обработчик может быть присвоен не двум, а любому количеству кнопок. И не только кнопкам. У остальных View-элементов тоже есть различные события, которые нуждаются в обработчиках. В дальнейшем мы еще будем с ними работать. А сейчас важно понять схему, как происходит обработка событий.

Отличие способа реализации на этом уроке от прошлого урока в том, что сейчас мы создали один объект-обработчик для обеих кнопок, а на прошлом уроке - два объекта, по одному каждой кнопке. Есть правило – чем меньше объектов вы создаете, тем лучше, т.к. под каждый объект выделяется память, а это достаточно ограниченный ресурс, особенно для телефонов. Поэтому создавать один обработчик для нескольких View это правильнее с точки зрения оптимизации. К тому же кода становится меньше и читать его удобнее.

Есть еще один способ создания обработчика, который вовсе не потребует создания объектов. Будет использоваться уже созданный объект – Activity

 

Activity, как обработчик

Кнопка присваивает себе обработчика с помощью метода setOnClickListener (View.OnClickListener l). Т.е. подойдет любой объект с интерфейсом View.OnClickListener. Почему бы классу Activity не быть таким объектом? Мы просто укажем, что Activity-класс реализует интерфейс View.OnClickListener и заполним метод onCreate.

Создадим для этого новый проект:
Project name: P0102_ActivityListener
Build Target: Android 2.3.3
Application name: ActivityListener
Package name: ru.startandroid.develop.activitylistener
Create Activity: MainActivity


Экран снова возьмем тот же самый:

<?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="horizontal">
    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_margin="30dp">
        <TextView
            android:layout_width="wrap_content"
            android:text="TextView"
            android:layout_height="wrap_content"
            android:id="@+id/tvOut"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="50dp">
        </TextView>
        <Button
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:id="@+id/btnOk"
            android:text="OK"
            android:layout_width="100dp">
        </Button>
        <Button
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:id="@+id/btnCancel"
            android:text="Cancel"
            android:layout_width="100dp">
        </Button>
    </LinearLayout>
</LinearLayout>

 

Подготовим объекты и добавим реализацию интерфейса (implements onClickListener)

public class MainActivity extends Activity implements OnClickListener {
 
   TextView tvOut;
   Button btnOk;
   Button btnCancel;
 
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
 
     // найдем View-элементы
     tvOut = (TextView) findViewById(R.id.tvOut);
     btnOk = (Button) findViewById(R.id.btnOk);
     btnCancel = (Button) findViewById(R.id.btnCancel);
   }
 }

 

OnClickListener подчеркнут красным, т.к. его нет в импорте. Поэтому CTRL+SHIFT+O и выбираем View.OnClickListener.

Теперь Eclipse ругается на класс MainActivity. Это происходит потому, что для класса прописан интерфейс, но нет реализации методов этого интерфейса. Исправим это с помощью Eclipse. Наведите курсор на MainAcivity и выберите Add unimplemented methods


Eclipse добавит знакомый нам метод onClick. Только теперь этот метод будет реализован в Activity, а не в отдельном объекте-обработчике. Соответственно Activity и будет выступать обработчиком.

Заполним метод точно так же как и раньше. Ничего не изменилось. Ему на вход так же подается View (на которой произошло событие), по Id мы определим, какая именно эта View и выполним соответствующие действия:

  public void onClick(View v) {
     // по id определеяем кнопку, вызвавшую этот обработчик
     switch (v.getId()) {
     case R.id.btnOk:
       // кнопка ОК
       tvOut.setText("Нажата кнопка ОК");
       break;
     case R.id.btnCancel:
       // кнопка Cancel
       tvOut.setText("Нажата кнопка Cancel");
       break;
     }
   }

  

Осталось в методе onCreate присвоить обработчик кнопкам. Это будет объект this, т.е. текущий объект MainActivity.

    btnOk.setOnClickListener(this);
    btnCancel.setOnClickListener(this);

 

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

Полный код:

public class MainActivity extends Activity implements OnClickListener {
 
   TextView tvOut;
   Button btnOk;
   Button btnCancel;
 
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
 
     // найдем View-элементы
     tvOut = (TextView) findViewById(R.id.tvOut);
     btnOk = (Button) findViewById(R.id.btnOk);
     btnCancel = (Button) findViewById(R.id.btnCancel);
 
     // присваиваем обработчик кнопкам
     btnOk.setOnClickListener(this);
     btnCancel.setOnClickListener(this);
   }
 
   @Override
   public void onClick(View v) {
     // по id определеяем кнопку, вызвавшую этот обработчик
     switch (v.getId()) {
     case R.id.btnOk:
       // кнопка ОК
       tvOut.setText("Нажата кнопка ОК");
       break;
     case R.id.btnCancel:
       // кнопка Cancel
       tvOut.setText("Нажата кнопка Cancel");
       break;
     }
   }
 
 }

 

Самая простая реализация обработчика

Есть еще один способ реализации. В layout-файле (main.xml) при описании кнопки пишем:

<Button
    android:id="@+id/btnStart"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="onClickStart"
    android:text="start">
</Button>

 

Т.е. используем атрибут onClick. В нем указываем имя метода из Activity. Этот метод и сработает при нажатии на кнопку.

Далее, добавляем этот метод в Activity (MainActivity.java). Требования к методу: public, void и на вход принимает View:

  public void onClickStart(View v) {
    // действия при нажатии на кнопку
  }

 

В методе прописываете необходимые вам действия, и они будут выполнены при нажатии кнопки.

 


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal