1.05k likes | 1.24k Views
第 16 章 首頁畫面小工具與硬體介面. 16-1 首頁畫面小工具 - 手機靜音切換 16-2 感測器與遊戲控制 - 跳跳球遊戲 16-3 相機 - 行車記錄器 16-4 相機與感測器的應用 - 聰明相機 16-5 藍芽 - 掃描藍芽裝置. 16-1 首頁畫面小工具 - 手機靜音切換. 16-1-1 顯示今天日期小工具 16-1-2 小工具與 IntentService 服務 - 手機靜音切換. 16-1 首頁畫面小工具 - 手機靜音切換.
E N D
第16章 首頁畫面小工具與硬體介面 • 16-1 首頁畫面小工具-手機靜音切換 • 16-2 感測器與遊戲控制-跳跳球遊戲 • 16-3 相機-行車記錄器 • 16-4 相機與感測器的應用-聰明相機 • 16-5 藍芽-掃描藍芽裝置
16-1 首頁畫面小工具-手機靜音切換 • 16-1-1 顯示今天日期小工具 • 16-1-2 小工具與IntentService服務-手機靜音切換
16-1 首頁畫面小工具-手機靜音切換 • 首頁畫面小工具(Home Screen Widget)也稱為應用程式小工具(App Widget)是位在行動裝置的首頁畫面中,可以與之互動的一種程式,其主要功能是提供使用者重要的更新資訊,例如:顯示目前行程、今天日期、現在時間、即時天氣、即時股票行情和背景播放音樂的詳細資料等。 • 當我們將小工具新增至首頁畫面後,它會佔用一塊固定區域來顯示應用程式提供的內容,使用者一樣可以透過小工具與應用程式進行互動,例如:手機靜音切換、切換WiFi、暫停或切換至下一首音樂等,如果擁有背景服務,我們還可以定時更新小工具顯示的內容。
16-1-1 顯示今天日期小工具步驟一:開啟和執行Android專案 • 顯示今天日期小工具是一個在首頁畫面顯示今天日期的小工具,它是使用紅色粗體的文字來顯示今天日期。 • 請啟動Eclipse IDE開啟Android專案Ch16_1_1,專案的活動類別沒有任何功能,它只是在TextView元件顯示一段文字內容,其執行結果如下圖所示:
16-1-1 顯示今天日期小工具步驟二:建立小工具的定義檔 • 建立小工具的首要工作是建立定義檔,用來定義小工具的尺寸和更新頻率,這是位在「res\xml」目錄下的XML檔appwidgetprovider.xml,在AndroidManifest.xml檔註冊小工具時也需參考此檔案,如下所示: <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="72dp" android:minHeight="72dp" android:updatePeriodMillis="1800000" android:initialLayout="@layout/widget"/>
16-1-1 顯示今天日期小工具步驟三:建立小工具介面的版面配置 • 小工具版面配置檔widget.xml是位在「res\layout」目錄,如下所示: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/widgettext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:textStyle="bold" android:textColor="#f00"/> </LinearLayout>
16-1-1 顯示今天日期小工具步驟四:繼承AppWidgetProvider類別覆寫相關方法1 • 首頁畫面小工具事實上就是一個廣播接收器,收到廣播後更新小工具顯示的內容,在Android SDK提供AppWidgetProvider提供者類別,我們可以直接繼承AppWidgetProvider類別覆寫相關方法來建立小工具,如下所示: public class DateAppWidget extends AppWidgetProvider { private SimpleDateFormat formatter = new SimpleDateFormat("\n\n\nyyyy年\nMM月dd日"); ..... }
16-1-1 顯示今天日期小工具步驟四:繼承AppWidgetProvider類別覆寫相關方法2 onDeleted()方法 • 當刪除1或多個小工具實例後,也就是將首頁畫面的小工具移至垃圾桶,AppWidget管理員物件會送出ACTION_APPWIDGET_DELETED 廣播,onDeleted()方法可以回應此廣播,程式碼只是使用Toast類別顯示呼叫此方法的訊息文字,如下所示: @Override public void onDeleted(Context context, int[] appWidgetIds) { Toast.makeText(context, "onDeleted()", Toast.LENGTH_LONG).show(); }
16-1-1 顯示今天日期小工具步驟四:繼承AppWidgetProvider類別覆寫相關方法3 onDisabled()方法 • 當刪除屬於此小工具的最後1個物件實例後,就會送出ACTION_APPWIDGET_DISABLED廣播,onDisabled()方法可以回應此廣播,程式碼只是使用Toast類別顯示呼叫此方法的訊息文字,如下所示: @Override public void onDisabled(Context context) { Toast.makeText(context, "onDisabled()", Toast.LENGTH_LONG).show(); }
16-1-1 顯示今天日期小工具步驟四:繼承AppWidgetProvider類別覆寫相關方法4 onEnabled()方法 • 當小工具初始化新增至首頁畫面後,就會送出ACTION_APPWIDGET_ENABLED廣播,onEnabled()方法可以回應此廣播,程式碼只是使用Toast類別顯示呼叫此方法的訊息文字,如下所示: @Override public void onEnabled(Context context) { Toast.makeText(context, "onEnabled()", Toast.LENGTH_LONG).show(); }
16-1-1 顯示今天日期小工具步驟四:繼承AppWidgetProvider類別覆寫相關方法5 onUpdate()方法 • 當小工具被要求更新RemoteViews物件的介面元件時,就會送出ACTION_APPWIDGET_UPDATE廣播,它就是在定義檔使用android:updatePeriodMillis 屬性指定的更新頻率,onUpdate()方法可以回應此廣播,更新小工具顯示的內容,如下所示: @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); String today = formatter.format(new Date()); RemoteViews remoteView = new RemoteViews( context.getPackageName(), R.layout.widget); remoteView.setTextViewText(R.id.widgettext, today); appWidgetManager.updateAppWidget(appWidgetIds, remoteView); Toast.makeText(context, "onUpdate()", Toast.LENGTH_LONG).show(); }
16-1-1 顯示今天日期小工具步驟五:在AndroidManifest.xml註冊小工具 • 最後我們需要在AndroidManifest.xml檔註冊小工具,也就是註冊廣播接收器,如下所示: <receiver android:name=".DateAppWidget" android:label="@string/app_name" android:icon="@drawable/icon"> <intent-filter> <action android:name= "android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidgetprovider" /> </receiver>
16-1-2 小工具與IntentService服務-手機靜音切換 • 在本節的手機靜音切換小工具擁有背景服務,可以送出Intent物件來更新小工具顯示的圖示,換句話說,按一下小工具可以切換鈴聲狀態成為靜音且顯示靜音圖示,再按一下就切換成正常且顯示正常圖示。 • 因為首頁畫面本身是一個在行動裝置上執行,名為啟動器的應用程式,小工具只是在首頁畫面中特定區域執行的程式,因為Android作業系統並不允許開發者修改執行中的程式碼,小工具為了能夠更新內容和與使用者互動,使用的是RemoteViews介面元件架構。 • RemoteViews介面元件架構允許在首頁畫面建立遠端控制的介面元件,換句話說,在首頁畫面顯示的是獨立行程執行的遠端介面元件,實際處理此介面的程式就是繼承AppWidgetProvider提供者類別的物件。 • 當使用者在小工具的遠端介面進行互動時,例如:按一下,Android作業系統就像是一個路由器,可以將此廣播轉向送至小工具來處理,例如:更新遠端介面元件的內容。
16-1-2 小工具與IntentService服務-手機靜音切換步驟一:開啟和執行Android專案 • 請啟動Eclipse IDE開啟Android專案Ch16_1_2,專案的活動類別沒有任何功能,它只是在TextView元件顯示一段文字內容,其執行結果如下圖所示:
16-1-2 小工具與IntentService服務-手機靜音切換步驟二:建立小工具的定義檔 • 此步驟的定義檔和第16-1-1節的步驟二完全相同,筆者就不重複說明。
16-1-2 小工具與IntentService服務-手機靜音切換步驟三:建立小工具介面的版面配置 • 小工具版面配置檔widget.xml是位在「res\layout」目錄,它是使用LinearLayout垂直編排一個ImageView元件,如下所示: <ImageView android:id="@+id/phoneState" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_centerInParent="true" android:src="@drawable/icon" android:clickable="true" />
16-1-2 小工具與IntentService服務-手機靜音切換步驟四:繼承AppWidgetProvider類別覆寫相關方法1 • 首頁畫面小工具是一個繼承AppWidgetProvider類別覆寫相關方法的提供者類別,如下所示: public class SilentAppWidget extends AppWidgetProvider { ..... }
16-1-2 小工具與IntentService服務-手機靜音切換步驟四:繼承AppWidgetProvider類別覆寫相關方法2 onRecieve()方法 • 通常覆寫onReceive()方法是用來呼叫AppWidgetProvider類別的其他方法,在此是處理使用者第1次在首頁畫面新增小工具時,能夠更新成目前的鈴聲狀態,if條件是呼叫Intent物件的getAction()方法檢查是否有動作,沒有,就呼叫startService()方法啟動ToggleSilentService服務來更新鈴聲狀態,如下所示: @Override public void onReceive(Context context, Intent intent) { if (intent.getAction() == null) { context.startService(new Intent(context, ToggleSilentService.class)); } else { super.onReceive(context, intent); } }
16-1-2 小工具與IntentService服務-手機靜音切換步驟四:繼承AppWidgetProvider類別覆寫相關方法3 onUpdate()方法 • 在onUpdate()方法呼叫參數Context物件的startService()方法啟動ToggleSilentService服務,如下所示: @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { context.startService(new Intent(context, ToggleSilentService.class)); }
16-1-2 小工具與IntentService服務-手機靜音切換步驟五:建立繼承IntentService類別的服務-1 • IntentService類別是Service類別的子類別,可以用來處理非同步Intent意圖的請求,每一個Intent物件是新增至佇列後再依序處理,即啟動執行緒來處理每一個Intent物件,當任務完成後就自動停止服務,並且可以使用廣播方式來將資料送回應用程式。 • 一般來說,當我們有任務需要在主執行緒外,啟動其他執行緒來執行此任務,以維持應用程式的執行效能時,或有多個處理請求,需要使用佇列來一一快速處理時,就可以繼承IntentService類別來建立服務,如下所示: public class ToggleSilentService extends IntentService { public ToggleSilentService() { super("ToggleSilentService"); } … }
16-1-2 小工具與IntentService服務-手機靜音切換步驟五:建立繼承IntentService類別的服務-2 onHandleIntent()方法 • onHandleIntent()方法是負責處理啟動服務的Intent物件,即處理步驟四呼叫startService()方法啟動服務的方法參數,執行緒是在請求行程後就會呼叫此方法,在每一個時間只有一個Intent物件會處理,如下所示: @Override protected void onHandleIntent(Intent arg0) { ComponentName cn = new ComponentName( this, SilentAppWidget.class); AppWidgetManager awManager = AppWidgetManager.getInstance(this); awManager.updateAppWidget(cn, updatePhoneStatus(this)); }
16-1-2 小工具與IntentService服務-手機靜音切換步驟五:建立繼承IntentService類別的服務-3 updatePhoneStatus()方法 • updatePhoneStatus()方法的傳回值是RemoteViews物件,它是使用AUDIO_SERVICE系統服務來更新手機的鈴聲狀態,方法首先從版面配置資源載入來建立RemoteViews物件,如下所示: private RemoteViews updatePhoneStatus(Context context) { RemoteViews remoteView = new RemoteViews( context.getPackageName(), R.layout.widget); AudioManager manager = (AudioManager) context.getSystemService(Activity.AUDIO_SERVICE);
16-1-2 小工具與IntentService服務-手機靜音切換步驟五:建立繼承IntentService類別的服務-4 if (manager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) { remoteView.setImageViewResource( R.id.phoneState, R.drawable.phone_on); manager.setRingerMode( AudioManager.RINGER_MODE_NORMAL); } else { remoteView.setImageViewResource( R.id.phoneState, R.drawable.phone_silent);
16-1-2 小工具與IntentService服務-手機靜音切換步驟五:建立繼承IntentService類別的服務-5 manager.setRingerMode( AudioManager.RINGER_MODE_SILENT); } Intent i = new Intent(this, SilentAppWidget.class); PendingIntent pi = PendingIntent.getBroadcast( context, 0, i, 0); remoteView.setOnClickPendingIntent(R.id.phoneState,pi); return remoteView; }
16-1-2 小工具與IntentService服務-手機靜音切換步驟六:在AndroidManifest.xml註冊小工具與服務 • 最後我們需要在AndroidManifest.xml檔註冊小工具與服務,也就是註冊廣播接收器和ToggleSilentService服務,如下所示: <receiver android:name=".SilentAppWidget" android:label="@string/app_name" android:icon="@drawable/icon"> <intent-filter> <action android:name= "android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidgetprovider" /> </receiver> <service android:name=".ToggleSilentService" />
16-2 感測器與遊戲控制-跳跳球遊戲 • 16-2-1 傾斜監測 • 16-2-2 感測器與遊戲控制-跳跳球遊戲
16-2 感測器與遊戲控制-跳跳球遊戲 • Android支援多種感測器來監測行動裝置目前的狀態,例如:數位羅盤、加速感測器、重力感測器、趨近感測器、陀螺儀和環境光線感測器等,請注意!行動裝置可能只支援其中幾項感測器,而且Android模擬器不支援感測器,我們只能使用實機來測試感測器。 • 在實務上,我們最常使用「加速感測器」(Accelerometer),所以本節是以加速感測器為例,說明如何應用在遊戲控制。
16-2-1 傾斜監測 • 傾斜監測是使用加速感測器判斷行動裝置目前是否傾斜。當我們取得感測器系統服務的ServiceManager物件後,就可以註冊SensorEventListener傾聽者物件來取得感測器的偵測資料,為了避免耗用過多電力,建議在onResume()方法註冊;onPause()方法取消註冊。
16-2-1 傾斜監測步驟一:開啟和執行Android專案 • 請啟動Eclipse IDE開啟Android專案Ch16_2_1,內含1個Java類別檔和版面配置檔main.xml,因為Android模擬器不支援感測器,筆者是使用2.3版的實機來測試,其執行結果如右圖所示:
16-2-1 傾斜監測步驟二:建立使用介面的版面配置-1 <TableLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="0,1,2"> <TableRow android:layout_weight="1"> <TextView android:id="@+id/top" android:layout_column="1"/> </TableRow> <TableRow android:layout_weight="1"> <TextView android:id="@+id/left" android:layout_column="0"/> <TextView android:id="@+id/right" android:layout_column="2"/> </TableRow>
16-2-1 傾斜監測步驟二:建立使用介面的版面配置-2 <TableRow android:layout_weight="1"> <TextView android:id="@+id/bottom" android:layout_column="1"/> </TableRow> </TableLayout> <TextView android:id="@+id/output" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true"/>
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-1 • 在Ch16_2_1Activity活動類別實作SensorEventListener介面的2個方法,類別開頭宣告成員的SensorManager、Sensor和TextView物件變數,如下所示: public class Ch16_2_1Activity extends Activity implements SensorEventListener { private SensorManager manager; private Sensor accelerometer; private TextView txtOutput, txtTop, txtBottom, txtLeft, txtRight; … }
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-2 onCreate()方法 • 在覆寫的onCreate()方法載入版面配置後,就可以取得感測器系統服務的SensorManager物件manager,如下所示: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); manager = (SensorManager) getSystemService( SENSOR_SERVICE); accelerometer = manager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER); txtOutput = (TextView) findViewById(R.id.output); txtTop = (TextView) findViewById(R.id.top); txtBottom = (TextView) findViewById(R.id.bottom); txtLeft = (TextView) findViewById(R.id.left); txtRight = (TextView) findViewById(R.id.right); }
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-3 onResume()方法 • 在覆寫onResume()方法註冊SensorEventListener傾聽者物件,即自己,如下所示: @Override protected void onResume() { super.onResume(); manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); }
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-4 onPause()方法 • 在覆寫onPause()方法取消註冊SensorEventListener傾聽者物件,如下所示: @Override protected void onPause() { super.onPause(); manager.unregisterListener(this); }
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-5 實作SensorEventListener介面的方法 • SensorEventListener傾聽者物件需要實作2個介面方法,不過,我們只有使用onSensorChanged()方法,這是當感測器資料改變時呼叫的方法,如下所示: @Override public void onAccuracyChanged(Sensor arg0, int arg1) { } @Override public void onSensorChanged(SensorEvent event) { float[] values = event.values; float x, y; int xFactor, yFactor; x = values[0] / 10; y = values[1] / 10;
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-6 xFactor = (int) Math.min(Math.abs(x) * 255, 255); yFactor = (int) Math.min(Math.abs(y) * 255, 255); if (x > 0) { txtRight.setBackgroundColor(Color.TRANSPARENT); txtLeft.setBackgroundColor( Color.argb(xFactor, 255, 255, 0)); } else { txtRight.setBackgroundColor(Color.argb(xFactor, 255, 255, 0)); txtLeft.setBackgroundColor( Color.TRANSPARENT); } if (y > 0) {
16-2-1 傾斜監測步驟三:建立Activity活動類別使用加速感測器-7 txtTop.setBackgroundColor(Color.TRANSPARENT); txtBottom.setBackgroundColor( Color.argb(yFactor, 255, 255, 0)); } else { txtTop.setBackgroundColor( Color.argb(yFactor, 255, 255, 0)); txtBottom.setBackgroundColor(Color.TRANSPARENT); } txtOutput.setText(String.format( "X軸: %1$1.2f, Y軸: %2$1.2f, Z軸: %3$1.2f", values[0], values[1], values[2])); }
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟一:開啟和執行Android專案 • 加速感測器最常應用在遊戲程式,這一節我們準備使用加速感測器來移動螢幕上的黃色球,可以傾斜行動裝置來控制球的滾動方向。 • 請啟動Eclipse IDE開啟Android專案Ch16_2_2,內含2個Java類別檔和版面配置檔main.xml,因為Android模擬器不支援感測器,筆者是使用2.3版的實機來測試,其執行結果如右圖所示:
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟二:建立使用介面的版面配置 • 使用介面的版面配置是定義在main.xml版面配置檔,只有一個FrameLayout版面配置,如下所示: <FrameLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/gameboard"> </FrameLayout>
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-1 • 在Ch16_2_2Activity活動類別實作SensorEventListener介面的2個方法,類別開頭宣告成員的SensorManager、Sensor、重繪的Handler、計時的Timer、TimerTask和PointF物件變數,如下所示: public class Ch16_2_2Activity extends Activity implements SensorEventListener { private SensorManager manager; private Sensor accelerometer; private MyBallView ball = null; private Handler redrawHandler = new Handler(); private Timer moveTimer = null; private TimerTask moveTask = null; private int sWidth, sHeight; private PointF ballPos, ballSpeed; … }
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-2 onCreate()方法 • 在覆寫onCreate()方法的開始是使用requestWindowFeature()方法來隱藏標題列,如下所示: @Override public void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(0xFFFFFFFF, LayoutParams.FLAG_FULLSCREEN | LayoutParams.FLAG_KEEP_SCREEN_ON); super.onCreate(savedInstanceState); setContentView(R.layout.main); final FrameLayout board = (FrameLayout) findViewById(R.id.gameboard);
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-3 Display display = getWindowManager().getDefaultDisplay(); sWidth = display.getWidth(); sHeight = display.getHeight(); ballPos = new PointF(); ballSpeed = new PointF(); ballPos.x = sWidth / 2; ballPos.y = sHeight / 2; ballSpeed.x = 0; ballSpeed.y = 0; ball = new MyBallView(this, ballPos.x, ballPos.y, 10); board.addView(ball); ball.invalidate();
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-4 manager = (SensorManager) getSystemService( SENSOR_SERVICE); accelerometer = manager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER); board.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, android.view.MotionEvent e) { ballPos.x = e.getX(); ballPos.y = e.getY(); return true; } }); }
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-5 onResume()方法 • 在覆寫onResume()方法首先註冊SensorEventListener傾聽者物件,即自己後,建立Timer計時器物件來移動黃色球至新位置,如下所示: @Override public void onResume() { manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); moveTimer = new Timer(); moveTask = new TimerTask() {
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-6 public void run() { Log.d("Ch16_2_2","更新時間 - " + ballPos.x + ":" + ballPos.y); ballPos.x += ballSpeed.x; ballPos.y += ballSpeed.y; float oX = 10 * Math.abs(ballSpeed.x); float oY = 10 * Math.abs(ballSpeed.y); if (ballPos.x > sWidth) ballPos.x -= oX; if (ballPos.y > sHeight) ballPos.y -= oY; if (ballPos.x < 0) ballPos.x += oX;
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-7 if (ballPos.y < 0) ballPos.y += oY; ball.updatePosition(ballPos.x, ballPos.y); redrawHandler.post(new Runnable() { public void run() { ball.invalidate(); } }); }}; moveTimer.schedule(moveTask, 10, 10); super.onResume(); }
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-8 onPause()方法 • 在覆寫onPause()方法呼叫cancel()方法取消Timer計時器物件和取消註冊SensorEventListener傾聽者物件,如下所示: @Override public void onPause() { moveTimer.cancel(); moveTimer = null; moveTask = null; super.onPause(); manager.unregisterListener(this); }
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟三:建立Activity活動類別使用加速感測器-9 實作SensorEventListener介面的方法 • SensorEventListener傾聽者物件需要實作介面的2個方法,我們只有使用onSensorChanged()方法,如下所示: @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { ballSpeed.x = -event.values[0]; ballSpeed.y = event.values[1]; }
16-2-2 感測器與遊戲控制-跳跳球遊戲步驟四:建立畫出黃色球的View介面類別-1 • 在螢幕上顯示的黃色球是一個繼承View類別的自訂介面元件,如下所示: public class MyBallView extends View { private float x; private float y; private final int r; private final Paint paint = new Paint( Paint.ANTI_ALIAS_FLAG); public MyBallView(Context context, float x, float y, int r) { super(context); paint.setColor(Color.YELLOW); this.x = x; this.y = y; this.r = r; }