Android事件

基于监听的事件处理

事件源:事件发生的产所,一般为各个控件

事件:在事件源上发生的事情,如单击,双击等等

事件监听器:负责监听事件源发生的事件,并对各种事件进行响应

基于监听的事件处理是一种委派式的事件处理方式,在这种处理方式中,事件源将整个事件处理委托给事件监听器进行处理,事件监听器调用相应的方法进行处理。委派式的处理方式将事件源和事件监听器进行分离,从某种程度上来说提高了程序的可读性。

基于内部类的事件监听方式

在类内部写一个监听器类,并实现监听接口。如下所示:

public ListenerTest extends AppActivity {
    private Button btn;
    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.main);
        
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new MyListensr());
    }
    
    class MyListensr implements View.OnClickListener {
        
        @Override
        public void OnClick (View v) {
            //事件处理操作
        }
    }
}

基于外部类的事件监听方式

有的时候当一个监听器需要被多个活动使用时,可以通过基于外部类的事件监听方式进行事件处理。如下所示

public ListenerTest extends AppActivity {
    private Button btn;
    private EditText address;
    private EditText content;
    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.main);
        
        btn = (Button)findViewById(R.id.btn);
        address = findViewById(R.id.address);
        content = findViewById(R.id.content);
        btn.setOnClickListener(new MyListensr(this, address, content));
    }
}
public MyListensr implements View.OnClickListener {
    private Activity activity;
    private EditText address;
    private EditText content;
	
    public MyListensr (Activity activity, EditText address, EditText content) {
        this.activity = activity;
        this.address = address;
        this.content = content;
    }
    
    @Override
    public void OnClick (View v) {
        //事件处理操作
    }
    
}

基于匿名内部类的事件监听方式

基于匿名内部类的方式使用最广泛,其使用到了java中的匿名内部类的语法。如下所示:

public ListenerTest extends AppActivity {
    private Button btn;
    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.main);
        
        btn = (Button)findViewById(R.id.btn);
        
        btn.setOnClickListener(new View.OnClickListener() {
            @Override 
            public void onClick(View v) {
                //事件处理操作
            }
        });
    }
}

基于接口实现或Activity自身响应

这种方式直接使用Activity作为监听器类,从而直接在活动中添加事件处理方法。如下所示:

public ListenerTest extends AppActivity implements View.OnClickListener{
    private Button btn;
    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.main);
        
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickener(this);
    }
    
    @Override
    public void onClick (View v) {
        switch(v.getId()) {
            case  R.id.btn:
                //事件处理操作
                break;
            default:
                break;
        }
    }
}

绑定到标签

通过UI布局,直接在UI布局中,设定其事件,如Android:OnClick,Android:On

LongClick等等。如下所示,在清单文件中添加一个Button

<Button
    android:id="@+id/btn"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content"
    android:onClick = "function"    
        />

在活动中定义该事件处理方法:

public ListenerTest extends AppActivitym {
    private Button btn;
    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.main);
        
    }
    
    public void function (View v) {
		//事件处理操作
    }
}

基于回调的事件处理

通过对基于监听的事件处理方式得知,基于监听的是将事件源与事件监听器分开。这里要讲的基于回调的事件处理是Android中另外一种事件处理方式,其与基于监听的事件处理方式截然相反。在基于回调的事件处理中事件源和事件监听均数据一个整体中的,相当于事件源和事件监听属于一个控件。其实现方式就是定义一个控件类并继承View 的控件类,此外,还需要重写父类中的事件处理方法。

Android 的View类中提供了许多事件处理方法,如下所示:

  • boolean onKeyDown(int keyCode, KeyEvent event):当用于在该控件按下时触发该方法
  • boolean onKeyLongPress(int keyCode, KeyEvent event):当用户长按控件时触发该方法
  • boolean onKeyUp(int keyCode, KeyEvent event):当用户在控件上按下后松开按键时触发该方法

除上面之外,还有许多事件处理方法,下面举例说明。

public MyButton extends Button {
    public MyButton () {
        
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        super.onKeyDown(keyCode, event);
        Log.d(TAG,"onKeyDown");
        //如果返回true,表明该事件不会向外扩散了
        return true;
    } 
}

在清单文件直接使用

<com.android.example.MyButton
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content"
    android:text = "test"
    android:id = "@+id/btn"
    />

通过上述例子可以看出onKeyDown返回了一个boolean值,其实在基于回调的事件处理中的大多数事件处理方法都会返回boolean值,该返回值得意义如下:

  • 如果返回true,表明该方法已经完全处理该事件,该事件不会传出去了
  • 如果返回false,表明该方法并没有完全处理该事件,该事件会传出去
public ListenerTest extends AppActivity{
    private Button btn;
    @Override
    public void onCreate(Bundle savedInstance) {
        super.onCreate(savedInstance);
        setContentView(R.layout.main);
        
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickener(new View.onClickListener{
            @override
            public boolean onKey (View v, int keyCode, KeyEvent event) {
                //事件处理操作
                Log.d(TAG,"onKey");
                return false;
            }
        });
    }
    
    @Override
    public boolean onKeyDown (int keyCode, KeyEvent event) {
        super.onKeyDown (keyCode, event);
        //事件处理操作
        Log.d(TAG,"onKeyDown");
      	return true;
    }
}

上述例子中,可以看出所有的事件处理方法中,都返回false,所以这些方法都没有完全处理该事件,意味着事件会被传播。在这种情况下,最先触发的是按键上绑定的事件处理方法,接着触发该控件类提供的回调方法,最后调用该活动提供的事件处理方法。