編輯:關於Android編程
現代的用戶界面,都是以事件來驅動的來實現人機交換的。而Android上的一套UI控件,無非就是派發鼠標和鍵盤事件,然後每個控件收到相應的事件之後,做相應的處理。如Button控件,就只需要處理Down、move、up這幾個事件,Down的時候重繪控件,move的時候一般也需要重繪控件,當up的時候,重繪控件,然後產生onClick事件。在Android中通過實現OnClickListener接口的onClick方法來實現對 Button控件的處理。
對於觸摸屏事件(鼠標事件)有按下有:按下、彈起、移動、雙擊、長按、滑動、滾動。按下、彈起、移動(down、move、up)是簡單的觸摸屏事件,而雙擊、長按、滑動、滾動需要根據運動的軌跡來做識別的。在Android中有專門的類去識別-----android.view.GestureDetector。
對於按鍵(keyevent),無非就是按下、彈起、長按等。
Android手機的坐標系是以左上定點為原點坐標(0,0),向右為X軸正方向,向下為Y軸正方向。
Android平台的事件處理機制有兩種:一種是基於回調的,一種基於事件監聽的。當然還有更復雜的手勢判別。對於基於監聽器的事件處理而言,主要就是為Android界面組件綁定特定的事件監聽器,如Button.setOnClickListener();對於基於回調的事件處理而言,主要做法是重寫Android組件特定的回調函數,Android大部分界面組件都提供了事件響應的回調函數,我們在需要時重寫它們就行,如在主活動中需要創建選項菜單,在主活動類中重寫onCreateOptionMenu()即可。下面做詳細解析:
相比基於監聽器的事件處理模型,基於回調的事件處理模型要簡單些,該模型中,事件源和事件監聽器是合一的,也就是說沒有獨立的事件監聽器存在。當用戶在GUI組件上觸發某事件時,由該組件自身特定的函數負責處理該事件。通常通過重寫Override組件類的事件處理函數實現事件的處理。
View類實現了KeyEvent.Callback接口中的一系列回調函數,因此,基於回調的事件處理機制通過自定義View來實現,自定義View時重寫這些事件處理方法即可。
1.publicinterfaceCallback{
2.//幾乎所有基於回調的事件處理函數都會返回一個boolean類型值,該返回值用於
3.//標識該處理函數是否能完全處理該事件
4.//返回true,表明該函數已完全處理該事件,該事件不會傳播出去
5.//返回false,表明該函數未完全處理該事件,該事件會傳播出去
6.booleanonKeyDown(intkeyCode,KeyEventevent);
7.booleanonKeyLongPress(intkeyCode,KeyEventevent);
8.booleanonKeyUp(intkeyCode,KeyEventevent);
9.booleanonKeyMultiple(intkeyCode,intcount,KeyEventevent);
10.}
例:
如果主活動中需要選項菜單,在定義好菜單的布局文件後,在主活動類中重寫幾個特定的方法即可完成菜單的創建和事件處理。
/**
* 創建可選菜單
* @param menu
* @return
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//加載[選項菜單的]布局文件
getMenuInflater().inflate(R.menu.main_opt_menu, menu);
return true;
}
/**
* 菜單被選中
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getGroupId() == R.id.group_sort){
//單選--排序組
item.setChecked(true);
}
switch (item.getItemId()){
case R.id.action_add:
Toast.makeText(MainActivity.this,"Add",Toast.LENGTH_SHORT).show();
break;
case R.id.action_search:
break;
default:break;
}
return true;
}
完整工程:https://github.com/ljheee/OptionMenu
相比於基於回調的事件處理,這是更具“面向對象”性質的事件處理方式。在監聽器模型中,主要涉及三類對象:
1)事件源EventSource:產生事件的來源;通常是各種組件,如按鈕,窗口等。
2)事件Event:事件封裝了界面組件上發生的特定事件的具體信息,如果監聽器需要獲取界面組件上所發生事件的相關信息,一般通過事件Event對象來傳遞。
3)事件監聽器EventListener:負責監聽事件源發生的事件,並對不同的事件做相應的處理。
基於監聽器的事件處理機制是一種委派式Delegation的事件處理方式,事件源將整個事件委托給事件監聽器,由監聽器對事件進行響應處理。這種處理方式將事件源和事件監聽分離,有利於提供程序的可維護性。
我們點擊一個按鍵時,可能就已經觸發好幾個事件,例如我們點擊數字鍵“0”,他會涉及到按下事件,和一個彈起(松開)事件;android中還可能涉及到觸摸屏事件;
在android中,事件的發生常在監聽器下進行,android系統可以響應按鍵事件和觸摸屏事件,事件說明如下:
lonClick(View v)一個普通的點擊按鈕事件
lbooleanonKeyMultiple(int keyCode,int repeatCount,KeyEvent event)用於在多個事件連續時發生,用於按鍵重復,必須重載@Override實現
lbooleanonKeyDown(int keyCode,KeyEvent event)用於在按鍵進行按下時發生
lbooleanonKeyUp(int keyCode,KeyEvent event)用於在按鍵進行釋放時發生
lonTouchEvent(MotionEventevent)觸摸屏事件,當在觸摸屏上有動作時發生
lbooleanonKeyLongPress(int keyCode, KeyEvent event)當你長時間按時發生
基於監聽器的事件模型符合單一職責原則,事件源和事件監聽器分開實現;
Android的事件處理機制保證基於監聽器的事件處理會優先於基於回調的事件處理被觸發;某些特定情況下,基於回調的事件處理機制會更好的提高程序的內聚性。
如下圖:在第一行EditText中輸入身高,點擊相應的按鈕,進過邏輯計算,顯示出“標准體重”。
BMI計算標准體重的公式:
男性:(身高cm - 80)* 70% = 標准體重
女性:(身高cm - 70)* 60% = 標准體重

創建 UI 的兩種方式:
– 在 XML 中聲明 UI 元素(推薦)
程序的 UI 呈現與代碼邏輯中分離
程序在不同的屏幕尺寸、屏幕方向及語言環境下加載不同的 XML 布局文件
– 在 Java 代碼中實例化 UI 元素


通過屬性onClick指定了一個方法名,即在Button按下就會執行對應的方法,這是Button點擊事件其中一種處理方式。但指定的方法名,在主活動類中需要定義相應的方法,且有要求:


除了使用屬性onClick指定了一個方法名進行事件處理外,還可以設置Button的點擊監聽器來完成事件處理。
工程代碼如下:
--------MainActivity.java
package com.example.administrator.bmiweight;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
//聲明所需控件
EditText editTextHeight;
TextView textViewWeight;
Button btnMale;
Button btnFemale;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//加載布局文件
//XML布局文件中的控件與 類前的聲明---做關聯
editTextHeight = (EditText) findViewById(R.id.editText_height);
textViewWeight = (TextView) findViewById(R.id.textView_weight);
btnMale = (Button) findViewById(R.id.button_male);
btnFemale = (Button) findViewById(R.id.button_female);
btnMale.setOnClickListener(newMyButtonHandle());//注冊監聽事件
btnFemale.setOnClickListener(newMyButtonHandle());
}
/**
* 內部類
* Button的事件監聽
*/
class MyButtonHandleimplements View.OnClickListener{
@Override
public void onClick(View v) {
//獲取輸入框--輸入值
String input = editTextHeight.getText().toString();
int weight = 0;
if(input.length()>0){
weight = Integer.parseInt(input);//數值轉化
}
int vid = v.getId();
switch (vid){
case R.id.button_male:
weight = (int)Math.ceil((weight-80)*0.7);
break;
case R.id.button_female:
weight = (int)Math.ceil((weight-70)*0.6);
break;
default:
break;
}
textViewWeight.setText(String.valueOf(weight));//設置顯示標准體重
}
}
/*
public void countWeight(View view) {
//獲取輸入框--輸入值
String input =editTextHeight.getText().toString();
int weight = 0;
if(input.length()>0){
weight =Integer.parseInt(input);//數值轉化
}
int vid = view.getId();
switch (vid){
case R.id.button_male:
weight =(int)Math.ceil((weight-80)*0.7);
break;
case R.id.button_female:
weight =(int)Math.ceil((weight-70)*0.6);
break;
default:
break;
}
textViewWeight.setText(String.valueOf(weight));//設置顯示標准體重
}
*/
}
--------XML布局文件代碼:
xml version="1.0" encoding="utf-8"?> <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="com.example.administrator.bmiweight.MainActivity"> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="number" android:ems="10" android:id="@+id/editText_height" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="身高" android:id="@+id/textView" android:layout_alignBaseline="@+id/editText_height" android:layout_alignBottom="@+id/editText_height" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="標准體重" android:id="@+id/textView2" android:layout_below="@+id/editText_height" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginTop="23dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView_weight" android:text="0" android:layout_alignTop="@+id/textView2" android:layout_toRightOf="@+id/button_male" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Male" android:id="@+id/button_male" android:layout_below="@+id/textView2" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginTop="33dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Female" android:id="@+id/button_female" android:layout_alignBottom="@+id/button_male" android:layout_alignRight="@+id/editText_height" android:layout_alignEnd="@+id/editText_height"/> RelativeLayout>
完整工程:https://github.com/ljheee/BMIWeight/tree/master
Android Builder模式詳解
經典Builder模式1) 定義:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。2) 經典的Builder模式有四個參與者Product:被構
Android-Universal-Image-Loader 源碼解讀
Universal-Image-Loader是一個強大而又靈活的用於加載、緩存、顯示圖片的Android庫。它提供了大量的配置選項,使用起來非常方便。基本概念基本使用首次
Android基礎入門教程——9.3 使用Camera拍照
Android基礎入門教程——9.3 使用Camera拍照標簽(空格分隔): Android基礎入門教程本節引言 本節給大家帶來的是Android
Android使用OKHttp包處理HTTP相關操作的基本用法講解
OKHttp是一款高效的HTTP客戶端,支持連接同一地址的鏈接共享同一個socket,通過連接池來減小響應延遲,還有透明的GZIP壓縮,請求緩存等優勢。(GitHub頁: