事件處理 靜宜大學資管系 楊子青
補充:物件導向的介面 (Interface) 現實世界中,許多『不同類』的事物,其間通常會具有一些相似的行為 例:飛機和小鳥顯然是不同的類別,飛行方式也不同,但均具有「飛行」的行為 為了不打亂原有的繼承架構,需要在各自的類別中定義各自的行為 在實作時避免造成遺漏或命名不一致,在 Java 中特別提供了介面(Interface)來描述這個共通的行為
Java有關Interface的語法 宣告Interface interface Shape { public double Shape_PI = 3.14; public double area(); public double perimeter(); }
Java有關Interface的語法 Class實作Interface class Circle implements Shape { private double radius; public Circle(double r) { setRadius(r); } public Circle() { this(10.0); public double getRadius() { return radius; public void setRadius(double r) { if (r > 0.0) { radius = r; } else { radius = 1; public double area() { return radius * radius * Shape_PI; public double perimeter() { return 2 * radius * Shape_PI;
Java有關Interface的語法 Class實作Interface class Rectangle implements Shape { private double length; private double width; public Rectangle(double l, double w) { setLength(l); setWidth(w); } public double area() { return length * width; public double perimeter() { return 2 * (length + width);
1. 事件處理之機制 來源物件與監聽物件
onClickListener介面
「計數器」專案Counter 選擇Empty Activity 修改成Linear Layout (vertical) TextView 重新命名id為@+id/txv text初值為0 textSize為36sp Layout_width設為match_parent gravity勾center
this表示MainActivity物件本身 2.讓txv也可以觸發Click,每次加1 加入介面宣告 public class MainActivity extends AppCompatActivity implements View.OnClickListener { onCreate方法,登錄監聽物件 TextView txv = (TextView) findViewById(R.id.txv); txv.setOnClickListener(this); 程式 int counter=0; public void onClick(View v) { counter++; txv.setText(Integer.toString(counter)); } this表示MainActivity物件本身 Integer.toString : 將 整數轉換成字串
3.加入按鈕進行歸零 Button元件 id為@+id/btn text為:歸零 textSize為36sp
讓btn觸發Click (不需在onClick屬性填method之作法) onCreate方法,登錄監聽物件 Button btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(this); 處理不同來源物件的相同事件(txv及btn均登錄了click事件) getId():判斷事件的來源物件
讓btn觸發Click,重設為0 int counter=0; public void onClick(View v) { if (v.getId() == R.id.txv){ counter++; } else{ counter = 0; TextView txv = (TextView) findViewById(R.id.txv); txv.setText(Integer.toString(counter));
4.讓txv觸發LongClick(長按)事件 加入介面宣告 public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnLongClickListener { onCreate方法,登錄監聽物件 TextView txv = (TextView) findViewById(R.id.txv); txv.setOnClickListener(this); txv.setOnLongClickListener(this); onLongClick()方法:需有boolean回傳值 true表示操作至此結束,手指放開不會再觸發click事件 false表示使用者放開手指,立即引發click事件
如果改成return dalse,每次會變成加3 讓txv觸發LongClick,每次加2 public boolean onLongClick(View v){ TextView txv = (TextView) findViewById(R.id.txv); counter += 2; txv.setText(String.valueOf(counter)); return true; } 長按數字,每次加2 如果改成return dalse,每次會變成加3 (長按加2後,又觸發click事件再加1)
5. onTouch(觸控)事件 可用來偵測「按下」與「放開」的動作 新增一個TextView 重新命名為@+id/txvvb 初始文字為「震動」 字體大小為36sp
onTouch事件 加入介面宣告 onCreate方法,登錄監聽物件 onTouch()方法:需有boolean回傳值 public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnLongClickListener, View.OnTouchListener { onCreate方法,登錄監聽物件 TextView txvvb = (TextView) findViewById(R.id.txvvb); txvvb.setOnTouchListener(this); onTouch()方法:需有boolean回傳值 true表示要處理接續的觸控事件,才能接收到手指放開的動作
如何讓手機震動? 需先至AndroidManifest.xml登記『震動』的使用權限 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tw.edu.pu.cs.tcyang.counter" > <uses-permission android:name="android.permission.VIBRATE"> </uses-permission> <application …
讓txvvb觸發onTouch事件,震動5秒 public boolean onTouch(View v, MotionEvent event){ Vibrator vb = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); vb.vibrate(5000); return true; } 利用event.getAction()傳遞的參數 可得知觸控的種類(按下或放開)
onTouch事件,判斷按下或放開
修改程式,讓手指移開則停止震動 public boolean onTouch(View v, MotionEvent e){ Vibrator vb = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (event.getAction() == MotionEvent.ACTION_DOWN){ vb.vibrate(5000); } else if (event.getAction() == MotionEvent.ACTION_UP){ vb.cancel(); return true; 建立apk,安裝到行動裝置試試看
常用的事件回撥方法 (Event Callback Methods) 傾聽者介面 事件來源 onClick() OnClickListener 觸摸螢幕或按下按鍵 onLongClick() OnLongClickListener 觸摸螢幕超過1秒鐘 onKey() OnKeyListener 按下行動裝置的按鍵 onTouch() OnTouchListener 觸摸螢幕 onFocusChange() OnFocusChange 焦點改變 onCreateContextMenu() 長按選單
實例:Kitty隨機變Lion 建立新的專案:Kitty 選擇Empty Activity 修改成Linear Layout (vertical) TextView 重新命名id為@+id/txv text初值為0 textSize為36sp Layout_width設為match_parent gravity勾center
放入kitty.png及lion.jpg 於res的drawable,按滑鼠右鍵,選show in Explorer,將兩張圖形檔copy進去
加入一個imageView元件 設定id屬性:「@+id/img」
使用者點選圖片,每次加1 監聽事件的另一種寫法 public class MainActivity extends AppCompatActivity { int Counter = 0; TextView txv; ImageView img; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txv = (TextView) findViewById(R.id.txv); img = (ImageView) findViewById(R.id.img); img.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Counter++; txv.setText(Integer.toString(Counter)); } }); 監聽事件的另一種寫法
隨機2~6次會從kitty變成lion (新增NewGame) int rnd; public void NewGame(){ Random x =new Random(); rnd = x.nextInt(5) + 2; img.setImageResource(R.drawable.kitty); }
隨機2~6次會從kitty變成lion (修改onCreate裡面的程式碼) img = (ImageView) findViewById(R.id.img); img.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Counter == 0) { NewGame(); } Counter++; txv.setText(Integer.toString(Counter)); if (Counter == rnd) { img.setImageResource(R.drawable.lion); Counter = 0; });
加入聲音檔 於res,按滑鼠右鍵,選show in Explorer,在裡面新建立raw資料夾,將兩個聲音檔copy進去
修改MainActivity.java程式 變數宣告部分 int Counter = 0; int rnd; TextView txv; ImageView img; MediaPlayer mediaPlayer;
修改onClick程式碼 設定及播放聲音 if (Counter == rnd) { img.setImageResource(R.drawable.lion); Counter = 0; mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.roar); } else{ mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.meow); mediaPlayer.start();
參考資料 施威銘主編,Android App程式設計教本之無痛起步 - 使用Android Studio開發環境,旗標出版社,2015年。 第4章:與使用者互動–事件處理