强强学Android_Android事件传递

学习资料 : 疯狂Android讲义_Android事件处理

学习笔记

如有错误之处请大家帮忙指出纠正__谢谢

-------------------------------------------------------------------------------------------------------------------------------------------

Android事件处理概念 :

当用户在程序应用界面上执行各种操作时,应用程序必须为用户提供响应动作,这种响应动作就需要通过事件处理来完成

Android提供了两种方式的事件处理: 基于回调的事件处理 和 基于监听的事件处理

一 : 基于监听的处理

事件监听主要涉及以下三类对象

Event Source [事件源]  事件的发生场所 , 通常就是各个组件,例如按钮, 窗口 , 菜单等

Event [事件]  事件封装了界面组件上发生的特定的事件, 比如用户在界面上按钮 , 移动,抬起 等等 , 一般通过Event对象来获得用户所做的事件

Event Listener[事件监听器]  负责监听事件源所发生的事件 , 并对各事件作出相应的响应

当用户按下按钮或者单击某个菜单选项的时候, 这些动作就会激发一个相应的事件 , 该事件就会触发事件源身上的事件监听器 , 事件监听器就会调用事件处理器(事件监听器里的实例方法)来作出相应的处理

事件处理流程事例图

点击事件: 

接下来的小案例 ; 按钮就是事件源,我们需要自己手动为事件源绑定事件监听器---事件监听器必须由开发者来实现

View.OnClickListener 实现了该接口的子类,必须实现未实现的方法 , 该类将会作为事件监听器使用,当按钮被点击时,他的方法,就是事件处理器,

我们可以在该方法中进行相应的操作

我们一般都是直接使用匿名内部类作为事件监听器类来使用

 1  1 package org.crazyit.event;
 2  2 import android.app.Activity;
 3  3 import android.os.Bundle;
 4  4 import android.view.View;
 5  5 import android.view.View.OnClickListener;
 6  6 import android.widget.Button;
 7  7 import android.widget.EditText;
 8  8 // 实现事件监听器接口
 9  9 public class ActivityListener extends Activity
10 10     implements OnClickListener
11 11 {
12 12     EditText show;
13 13     Button bn;
14 14     @Override
15 15     public void onCreate(Bundle savedInstanceState)
16 16     {
17 17         super.onCreate(savedInstanceState);
18 18         setContentView(R.layout.main);
19 19         show = (EditText) findViewById(R.id.show);
20 20         bn = (Button) findViewById(R.id.bn);
21 21         // 直接使用Activity作为事件监听器
22 22         bn.setOnClickListener(this);
23 23     }
24 24     // 实现事件处理方法
25 25     @Override
26 26     public void onClick(View v)
27 27     {
28 28         show.setText("bn按钮被单击了!");
29 29     }
30 30 }

 1  1 <?xml version="1.0" encoding="utf-8"?>
 2  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3  3     android:orientation="vertical"
 4  4     android:layout_width="fill_parent"
 5  5     android:layout_height="fill_parent"
 6  6     android:gravity="center_horizontal"
 7  7     >
 8  8 <EditText
 9  9     android:id="@+id/show"
10 10     android:layout_width="fill_parent"
11 11     android:layout_height="wrap_content"
12 12     android:editable="false"
13 13     />
14 14 <Button
15 15     android:id="@+id/bn"
16 16     android:layout_width="wrap_content"
17 17     android:layout_height="wrap_content"
18 18     android:text="单击我"
19 19     />
20 20 </LinearLayout>

  1. 基于监听的事件处理规则

(1)事件源: button,任何组件都可以作为事件源

(2)事件监听器: OnXXXListener , 该类必须由我们手动实现, 最关键的一步就是使用该类中的方法

(3)注册监听器: 事件源 . setOnXXXListener

事件监听处理中,主要涉及三个成员 , 事件源, 事件, 事件监听器

事件源就是控件,

事件: 具体是什么事件,是由系统产生的, 我们不用考虑 ;

实现事件监听器 , 是整个事件处理的核心

在上面的小案例中,我们并为发现事件的踪迹, 这是因为android对事件监听模型做了进一步的简化 , 如果事件源触发的事件足够简单,就无需封装事件对象, 直接将该事件传递到事件监听器中了

二 : 基于回调的事件处理

为了实现回调机制的事件处理, Android为所有的View组件都提供了一些事件处理的回调方法 , 以View为例,

小案例 :

基于回调事件处理机制通过自定义View实现 , 自定义View直接重写该View的事件处理方法即可 , 这里我们自定义Button为例

  1.  1 package org.crazyit.event;
     2 import android.content.Context;
     3 import android.util.AttributeSet;
     4 import android.util.Log;
     5 import android.view.KeyEvent;
     6 import android.widget.Button;
     7 public class MyButton extends Button
     8 {
     9     public MyButton(Context context, AttributeSet set)
    10     {
    11         super(context, set);
    12     }
    13     @Override
    14     public boolean onKeyDown(int keyCode, KeyEvent event)
    15     {
    16         super.onKeyDown(keyCode, event);
    17         Log.v("-crazyit.org-", "the onKeyDown in MyButton");
    18         // 返回true,表明该事件不会向外扩散
    19         return true;
    20     }
    21 }

  2. 直接在xml中使用该控件

onKeyDown这个方法,会负责处理该按钮上的键盘事件

我们将程序运行到模拟器上,使按钮获取焦点, 按下电脑的键盘任意键, Log就会打印日志

总结 : 对于监听事件处理来说 , 事件处理和事件源是分开的,当发生特定事件之后,事件将会传递给事件监听类中的事件处理方法

对于回调事件处理来说 , 事件处理和事件源是统一的,当发生特定的事件之后,该事件由事件源本身处理

基于回调的事件传播 : 

几乎所有的回调处理事件都有一个boolean类型返回值, 该返回值用于标示该处理方法是否完全处理该事件

返回true: 完全处理该事件, 事件不会再进行传播

返回false: 该处理方法并为完全处理该事件 , 事件会继续传播出去

对于基于回调的事件传播而言, 某组件身上所发生的事件 , 不仅激发该组件身上的回调方法, 也会触发该组件所在的Activity的回调方法 -->前提是事件能传递到该Activity

小案例:

重写Button的onKeyDown方法

重写该控件所在Activity的onKeyDown方法

程序不阻止事件传播, 我们将看到事件将传递到Activity中

 1 public class MyButton extends Button
 2 {
 3     public MyButton(Context context , AttributeSet set)
 4     {
 5         super(context , set);
 6     }
 7     @Override
 8     public boolean onKeyDown(int keyCode, KeyEvent event)
 9     {
10         super.onKeyDown(keyCode , event);
11         Log.v("-MyButton-" , "the onKeyDown in MyButton");
12         // 返回false,表明并未完全处理该事件,该事件依然向外扩散
13         return false;
14     }
15 }

 1 public class Propagation extends Activity
 2 {
 3     @Override
 4     public void onCreate(Bundle savedInstanceState)
 5     {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.main);
 8         Button bn = (Button) findViewById(R.id.bn);
 9         // 为bn绑定事件监听器
10         bn.setOnKeyListener(new OnKeyListener()
11         {
12             @Override
13             public boolean onKey(View source
14                     , int keyCode, KeyEvent event)
15             {
16                 // 只处理按下键的事件
17                 if (event.getAction() == KeyEvent.ACTION_DOWN)
18                 {
19                     Log.v("-Listener-", "the onKeyDown in Listener");
20                 }
21                 // 返回false,表明该事件会向外传播
22                 return false; // (1)
23             }
24         });
25     }
26     // 重写onKeyDown方法,该方法可监听它所包含的所有组件的按键被按下事件
27     @Override
28     public boolean onKeyDown(int keyCode, KeyEvent event)
29     {
30         super.onKeyDown(keyCode , event);
31         Log.v("-Activity-" , "the onKeyDown in Activity");
32         //返回false,表明并未完全处理该事件,该事件依然向外扩散
33         return false;
34     }
35 }

接下来我们通过Log看下事件传递的顺序

当该组件上发生某个按键被按下的事件时, 

[1]Android系统最先触发的是该控件身上绑定的事件监听器 ,

[2]前提第一步返回false, 接下来触发该组件中提供的事件回调方法

[3]前提第二步返回false,最终事件将会传递到Activity中的回调方法

反例 :

如果我们将监听器中的回调方法返回值返回true , 证明该方法完全处理该事件 , 事件将不会再进行传递

Log打印:

--------------------------------------------------------------------------------------------------------------------------------

重写onTouchEvent方法响应触摸屏事件

基于监听事件处理方式 更加强大, 事件源, 事件监听由两个类分开实现 , 因此具有更好的可维护性

android的事件处理机制保证基于监听的事件监听器会被优先触发

通过手指移动实现跟随手势移动的小球

  1.  1 public class DrawView extends View
     2 {
     3     public float currentX = 40;
     4     public float currentY = 50;
     5     // 定义、创建画笔
     6     Paint p = new Paint();
     7     public DrawView(Context context, AttributeSet set)
     8     {
     9         super(context, set);
    10     }
    11     @Override
    12     public void onDraw(Canvas canvas)
    13     {
    14         super.onDraw(canvas);
    15         // 设置画笔的颜色
    16         p.setColor(Color.RED);
    17         // 绘制一个小圆(作为小球)
    18         canvas.drawCircle(currentX, currentY, 15, p);
    19     }
    20     @Override
    21     public boolean onTouchEvent(MotionEvent event)
    22     {
    23         // 当前组件的currentX、currentY两个属性
    24         this.currentX = event.getX();
    25         this.currentY = event.getY();
    26         // 通知改组件重绘
    27         this.invalidate();
    28         // 返回true表明处理方法已经处理该事件
    29         return true;
    30     }
    31 }

    通过实验我们发现 , 小球会跟随我们的手指进行移动

上述代码中我们直接自定义View重写了onTouchEvent方法, 这表示该组件自己就可以处理触摸事件,,并不用为该View绑定事件监听器 ,

通过为View提供事件处理的回调方法,可以很好的将事件处理的方法封装到View内部, 基于回调事件处理更适合应付那种事件处理逻辑比较固定的View

来自为知笔记(Wiz)

时间: 2024-08-06 07:54:41

强强学Android_Android事件传递的相关文章

Atitit. &#160;Js 冒泡事件阻止&#160;事件捕获&#160;&#160;&#160;事件传递 &#160;事件代理

Atitit.  Js 冒泡事件阻止 事件捕获   事件传递  事件代理   1. 事件冒泡1 2. 事件捕获1 3. 同时支持了事件捕获阶段和事件冒泡阶段ddEventListener的第三个参数1 4. 事件代理3 5. 冒泡还是捕获?3 6. Js 冒泡事件阻止3 6.1. 返回false5 7. 事件冒泡 使处理函数有范围较大的触发面积,在“拖拽效果”脚本中是必须的5 8. refe6 8.1.1. 浅谈事件冒泡与事件捕获 - ac黄博客精选 - SegmentFault6   1. 事

事件传递之一(基本概念)

Android事件传递机制之一 所谓事件传递是指在Android应用程序开发中,当有多个View叠加在同一个区域内,如果按下View所在的区域,按下的Down.Move,Up事件将如何进行传递的过程. 假设一个ViewGroup里面包含了一个View,当用户按下View时,ViewGroup和View有哪些方法会触发呢. 在了了解这些事件传递之前,我们先来了解一下几个方法的概念: 1. dispatchTouchEvent:此方法只有继承ViewGroup的类才有,是指向childView分发事

iOS响应事件传递, nextResponder研究

这里,我们考虑以下二种情况. 问题1. 如何调用父view的controller里面的方法? 答案如下:[[self superview ].nextResponder  method];[[[self superview ] nextResponder]  method];[self.nextResponder method];上面的都可以,看情况使用,使用的时候最好判断一下. 官方解释UIView implements this method by returning the UIViewC

Android Touch事件传递机制解析

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵.. android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEvent ev)          这个方法用来分发TouchEvent 2)public boolean onInterceptTouchEvent(MotionEv

Android touch 事件传递机制

前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事件进行拦截.这个时候我们就需要明白android touch 事件传递机制, (2)以前很多时候比较模糊,也许是网上看到也有很多事件传递的相关文章,但我看着头晕,解释不彻底,有的说得一半,总算不满足不满意,于是据我自己的理解来彻底的来整理下具体的是怎么个传递方式,分享给大家,希望大家看到有什么不对的

iOS中的事件传递和响应者链条

iOS中的事件传递和响应者链条 本文转自:http://www.linuxidc.com/Linux/2015-08/121270.htm 首先我们来看看ios中事件的产生和传递过程 1.发生触摸事件后,系统会将事件加入到一个由UIApplication管理的队列事件中来 2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会发发送事件给应用程序的主窗口 3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件 4.找到合适的视图控件后,就会调用视图

iOS中的事件传递和响应者链

首先我们来看看iOS中事件的产生和传递过程: 1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中 2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow) 3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件 4.找到合适的视图控件后,就会调用视图控件的touches方法来作事件的具体处理:touchesBegin... touchesMoved...touch

Android中事件传递机制的总结

事件传递虽然算不上某个单独的知识点,但是在实际项目开发中肯定会碰到,如果不明白其中的原理,那在设计各种滑动效果时就会感到很困惑. 关于事件的传递,我们可能会有以下疑问: 事件是如何传递的 事件是如何处理的 自定义view的时候,事件也冲突了怎么解决 带着这三个疑问,我们来总结一下事件传递机制是怎么回事. 一.事件分发的原理: 1.事件是如何传递的: (1)首先由Activity分发,分发给根View,也就是DecorView(DecorView为整个Window界面的最顶层View) (2)然后

Android ViewGroup 触摸事件传递机制

引言 上一篇博客我们学习了Android View 触摸事件传递机制,不了解的同学可以查看Android View 触摸事件传递机制.今天继续学习Android触摸事件传递机制,这篇博客将和大家一起探讨ViewGroup的触摸事件传递机制. 示例 示例代码如下: public class MainActivity extends ActionBarActivity { private String TAG = "MainActivity"; private MyViewGroup pa