Android – Quản lý sự kiện (Event handling)



Event (sự kiện) là cách hữu dụng để thu thập dữ liệu về tương tác của người dùng trên ứng dụng. Ví dụ như là bấm nút hoặc là chạm vào màn hình. Framework Android quản lý một dãy các Event theo kiểu first-in, first-out (FIFO), có thể tạm dịch là vào trước thì ra trước. Bạn có thể bắt các Event này trong code và thêm các lệnh theo ý muốn.

Có 3 khái niệm liên quan đến quản lý các Event trong Android.

  • Event Listener − Là một Interface trong lớp View, Interface này chỉ chứa 1 phương thức callback. Các phương thức này sẽ được gọi bởi Framework Android khi mà View trong đó Listener đã đăng ký bị kích hoạt bởi tương tác của người dùng lên các UI Control.
  • Đăng ký Event Listener (Event Listener Registration) − Event Registration là một Process (quá trình) mà trong đó Event Handler được đăng ký với Event Listener, lúc này Handler được gọi khi Event Listener bị kích hoạt bởi Event.
  • Event Handler − Khi một Event xảy ra và ta đã đăng ký một Event Listener cho Event, Event Listener gọi Event Handler, đó chính là phương thức thực sự xử lý Event.

Một số Event Listener & Event Handler

Event Handler Event Listener & Mô tả
onClick() OnClickListener() Được gọi khi người dùng hoặc là bấm (click) hoặc chạm (touch) hoặc chuyển Focus lên bất kỳ Widget nào như Button, Text, Image… Bạn sẽ dùng Event Handler onClick() để xử lý những Event như thế này.
onLongClick() OnLongClickListener()  Được gọi khi người dùng hoặc là bấm (click) hoặc chạm (touch) hoặc chuyển focus lên bất kỳ Widget nào như Button, Text, Image… trong thời gian 1 giây hoặc dài hơn. Bạn sẽ dùng Event Handler onLongClick() để xử lý những Event như thế này.
onFocusChange() OnFocusChangeListener()  Được gọi khi Widget mất Focus, ví dụ như là người dùng rời khỏi View. Bạn sẽ dùng Event Handler onFocusChange() để xử lý Event này.
onKey() OnFocusChangeListener()  Được gọi khi người dùng được Focus lên một Item nào đó và bấm (press) hoặc thả (release) một phím trên thiết bị. Bạn sẽ dùng Event Handler onKey() để xử lý Event này.
onTouch() OnTouchListener()  Được gọi khi người dùng bấm (press) một phím, thả phím hoặc di chuyển gesture trên màn hình. Bạn sẽ dùng Event Handler onTouch() để xử lý Event này.
onMenuItemClick() OnMenuItemClickListener() Được gọi khi người dùng chọn một Item nào đó trong Menu. Bạn sẽ dùng Event Handler onMenuItemClick() để xử lý Event này.
onCreateContextMenu() onCreateContextMenuItemListener() Được gọi khi Context Menu được tạo, là kết quả của thao tác bấm và giữ (long click).

Có nhiều Event Listener khác nữa, chúng là một phần của lớp View giống như OnHoverListener, OnDragListener… Bạn có thể tham khảo tài liệu chính thức của Android về các Event Listener, cái mà có thể cần cho bạn khi lập trình ứng dụng.

Đăng ký Event Listener (Event Listener Registration)

Đăng ký Event (Event Registration) là một Process (quá trình) trong đó một Event Handler được đăng ký với một Event Listener. Event Handler sẽ được gọi khi Event Listener kích hoạt Event. Mặc dù có nhiều cách để đăng ký Event Listener cho bất kỳ Event nào, tôi xin đưa ra 3 cách theo tôi là thông dụng nhất:

  • Dùng lớp Anonymous Inner (Anonymous Inner Class)
  • Lớp Activity viết lại Interface Listener.
  • Dùng tập tin Layout activity_main.xml để chỉ định Event Handler một cách trực tiếp.

Sau đây sẽ là ví dụ chi tiết về 3 cách đăng ký Event:

Touch Mode (Chế độ cảm ứng)

Người dùng có thể tương tác với thiết bị bằng cách dùng bàn phím hoặc Button (nút bấm) hoặc là chạm vào màn hình cảm ứng. Chạm vào màn hình cảm ứng sẽ làm cho thiết bị nằm trong chế độ cảm ứng, hay còn gọi là Touch Mode. Người dùng có thể tương tác với thiết bị bằng cách chạm vào các Button (nút bấm), Image (hình ảnh)… Bạn có thể kiểm tra rằng thiết bị có đang nằm trong chế độ Touch Mode bằng phương thức isInTouchMode() của lớp View.

Touch Event (Sự kiện cảm ứng)

Focus

Một View hoặc Widget thường sáng lên hoặc có dấu nháy khi nó được Focus. Điều này thể hiện rằng nó sẵn sàng nhận Input (nhập liệu) từ người dùng.

  • isFocusable() – trả về true nếu View được Focus hoặc false trong trường hợp ngược lại.
  • isFocusableInTouchMode() – kiểm tra View có đang được Focus trong chế độ Touch Mode. (Một View cũng có thể được Focus bằng cách sử dụng phím cứng, khi đó nó không nằm trong chế độ Touch Mode, trong trường hợp này phương thức sẽ trả về giá trị false).
android:focusUp="@=id/button_l"

onTouchEvent()

public boolean onTouchEvent(motionEvent event){
   switch(event.getAction()){
      case TOUCH_DOWN:
      Toast.makeText(this,"you have clicked down Touch button",Toast.LENTH_LONG).show();
      break();
   
      case TOUCH_UP:
      Toast.makeText(this,"you have clicked up touch button",Toast.LENTH_LONG).show();
      break;
   
      case TOUCH_MOVE:
      Toast.makeText(this,"you have clicked move touch button"Toast.LENTH_LONG).show();
      break;
   }
   return super.onTouchEvent(event) ;
}

Ví dụ xử lý Event

Đăng ký Event Listener dùng lớp Anonymous Inner

Ở đây bạn sẽ tạo một Anonymous Implementation của Listener. Sau đây là các bước đơn giản chỉ dẫn cách dùng một lớp Listener để đăng ký và bắt sự kiện Click. Bằng cách tương tự này, bạn có thể áp dụng đối với các Event khác.

Bước Mô tả
1 Trong IDE tạo một ứng dụng Android và đặt tên là myapplication dưới package com.example.myapplication.
2 Trong file src/MainActivity.java thêm Click Event Listener và Click Event Handler cho 2 Button.
3 Thêm UI Control vào file res/layout/activity_main.xml.
4 Không cần chỉnh sửa file value.xml.
5 Chạy ứng dụng trên Android Emulator và kiểm tra kết quả.

Sau đây là nội dung file src/com.example.myapplication/MainActivity.java đã chỉnh sửa:

package com.example.myapplication;

public class MainActivity extends ActionBarActivity {
   private ProgressDialog progress;
   Button b1,b2;
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      progress = new ProgressDialog(this);
      
      b1=(Button)findViewById(R.id.button);
      b2=(Button)findViewById(R.id.button2);
      b1.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            TextView txtView = (TextView) findViewById(R.id.textView);
            txtView.setTextSize(25);
         }
      });
      
      b2.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            TextView txtView = (TextView) findViewById(R.id.textView);
            txtView.setTextSize(55);
         }
      });
   }
   
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
   }
   
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      
      int id = item.getItemId();
      
      //noinspection SimplifiableIfStatement
      if (id == R.id.action_settings) {
         return true;
      }
      return super.onOptionsItemSelected(item);
   }
}

Sau đây là nội dung file res/layout/activity_main.xml đã chỉnh sửa:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context=".MainActivity">
   
   <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Event Handling "
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:textSize="30dp"/>
      
   <TextView
      android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Tutorials point "
      android:textColor="#ff87ff09"
      android:textSize="30dp"
      android:layout_above="@+id/imageButton"
      android:layout_centerHorizontal="true"
      android:layout_marginBottom="40dp" />
      
   <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/imageButton"
      android:src="@drawable/abc"
      android:layout_centerVertical="true"
      android:layout_centerHorizontal="true" />
      
   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Small font"
      android:id="@+id/button"
      android:layout_below="@+id/imageButton"
      android:layout_centerHorizontal="true" />
      
   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Large Font"
      android:id="@+id/button2"
      android:layout_below="@+id/button"
      android:layout_alignRight="@+id/button"
      android:layout_alignEnd="@+id/button" />
      
   <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Hello World!"
      android:id="@+id/textView"
      android:layout_below="@+id/button2"
      android:layout_centerHorizontal="true"
      android:textSize="25dp" />
      
</RelativeLayout>

Following will be the content of res/values/strings.xml to define two new constants −

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="app_name">myapplication</string>
   <string name="action_settings">Settings</string>
</resources>

Following is the default content of AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.myapplication"
   android:versionCode="1"
   android:versionName="1.0" >
   
   <uses-sdk
      android:minSdkVersion="8"
      android:targetSdkVersion="22" />
      
   <application
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" >
      
      <activity
         android:name="com.example.myapplication.MainActivity"
         android:label="@string/app_name" >
      
         <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
      
      </activity>
      
   </application>
</manifest>

Chạy ứng dụng, trên Emulator và thử Click và 2 Button, bạn sẽ thấy Font của chuỗi Hello World thay đổi.

Bài tập

Hãy thử viết các Event Handler khác nhau cho các Event để hiểu thêm về các loại Event cũng như cách xử lý chúng. Lưu ý rằng các Event liên quan tới Menu, Spinner, Pickers thì hơi khác so với các Event được nhắc tới ở trên.

2167 Total Views 2 Views Today