Android开发基础:事件传递 基于监听器的事件处理 基于回调的事件处理

目录

一,事件传递机制

1.事件传递机制的三个方法 

(1)public boolean dispatchTouchEvent(MotionEvent event)

(2)public boolean onInterceptTouchEvent(MotionEvent event)

(3)public boolean onTouchEvent(MotionEvent event)

 2.事件传递的流程

二,基于监听器的事件处理

 1.基于监听器事件处理的三种实现方法

(1)匿名内部类实现

(2)内部类实现

(3)Activity直接实现接口

三,基于回调的事件处理


一,事件传递机制

        在Android中,每触摸或点击一次,就会生成一个MotionEvent对象,代表一次触摸事件。Android的事件传递主要由三个方法来完成:

  1. 事件分发:dispatchTouchEvent();
  2. 事件拦截:onInterceptTouchEvent();
  3. 事件响应:onTouchEvent();

         三种方法均返回boolean类型的值,表示是否解决事件。对于ViewGroup类,会进行事件分发,拦截,响应三种操作。但对于View来说,只有事件分发和响应,因为View没有子View,无法再向下传递,也就不需要事件拦截。

1.事件传递机制的三个方法 

(1)public boolean dispatchTouchEvent(MotionEvent event)

        事件分发方法,在Android中,事件首先到达Activity的顶层视图。在事件传递到Activity和View时,都会首先调用分发方法,如果子View的分发方法或当前View的响应方法能够成功解决事件,则返回true,表示当前事件已自我消化,否则返回false。

(2)public boolean onInterceptTouchEvent(MotionEvent event)

        事件拦截方法,View调用拦截方法后,会接着调用自己的响应方法去处理事件,并且如果某个View调用了拦截方法,那么它的父类View就不会再调用拦截方法,子类View成功处理了事件,父类View同样不会调用拦截方法。

(3)public boolean onTouchEvent(MotionEvent event)

        事件处理方法,成功处理返回true,否则返回false,子类View成功处理事件后,父类View不会再调用处理方法。

三种方法的关系用伪代码表示即为:

public boolean dispatchTouchEvent(MotionEvent event) {
	boolean isSolve = false;
	if(onInterceptTouchEvent(event)) {
		isSolve = onTouchEvent(event);
	} else {
		isSolve = child.dispatchTouchEvent(event);
	}
	
	return isSolve;
}

 2.事件传递的流程

        上图为事件传递的流程,由图可知事件传递的顺序为:Activity->ViewGroup->View。事件首先到达Activity的顶层视图,然后调用Activity的事件分发方法,随后事件被传递给最顶层ViewGroup,并调用ViewGroup的分发方法,若ViewGroup拦截事件,则交给ViewGroup的处理方法。若不拦截则继续调用子View的分发方法。如果最终事件没有被任何View处理,则返回给Activity处理。

二,基于监听器的事件处理

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

基于监听器的事件处理,涉及到三个核心对象:

  1. 事件源:事件发生的场所(View或ViewGroup);
  2. 事件:用户界面上发生的具体事件;
  3. 事件监听器:负责监听事件源所发生的事件,并作出响应;

 基于监听器的原理就是把事件源事件处理器(监听器)分离,让监听器去处理事件。实现方法就是为视图控件绑定特定的事件监听器。

 1.基于监听器事件处理的三种实现方法

 实现监听器处理事件,或者说是给View绑定监听器的三种常用方法为:

(1)匿名内部类实现

private Button btn_login = findViewById(R.id.btn_login);
btn_login.setOnClickListener( v ->{
    //获取输入内容,用对话框提示出来
    String name = edt_name.getText().toString(); //获取用户名
    String passWard = edt_passward.getText().toString(); //获取密码
    //对话框提示
    Toast.makeText(
        LoginActivity.this,
        "登陆成功:" + name,
        Toast.LENGTH_LONG).show();
        //在哪显示 + 显示内容 + 显示时长
 
});

(2)内部类实现

使用匿名内部类需要一个控件实现一个匿名内部类,使用成员内部类,可实现代码复用

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_practice);
 
        Button btn_login = findViewById(R.id.btn_login);
 
        //2.内部类 便于代码复用 建议使用
        Listener listener = new Listener();
        btn_login.setOnClickListener(listener);  //绑定监听器
        btn_enroll.setOnClickListener(listener);
 
 
    }
class Listener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            //因为同一对象被多个方法调用,所以需要用id来区分
            int id = v.getId();
            if(id == R.id.btn_login){
                String userName = edt_name.getText().toString();
                String passward = edt_passward.getText().toString();
                Toast.makeText(PracticeActivity.this, "欢迎登录!" + userName, Toast.LENGTH_SHORT).show();
            }
            else{
                String userName = edt_name.getText().toString();
                Toast.makeText(PracticeActivity.this, "注册成功!" + userName, Toast.LENGTH_SHORT).show();
                //日志打印
                Log.i("LoginActivity", "用户注册");
            }
        }
    }

(3)Activity直接实现接口

直接让Activity实现监听器接口,实现监听方法,控件绑定监听器,通过this调用onClick方法。

public class PracticeActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_practice);

        Button btn_login = findViewById(R.id.btn_login);
        Button btn_enroll = findViewById(R.id.btn_enroll);

        btn_enroll.setOnClickListener(this);
        btn_login.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if(id == R.id.btn_login){
            String userName = edt_name.getText().toString();
            String passward = edt_passward.getText().toString();
            Toast.makeText(PracticeActivity.this, "欢迎登录!" + userName, Toast.LENGTH_SHORT).show();
        }
        else{
            String userName = edt_name.getText().toString();
            Toast.makeText(PracticeActivity.this, "注册成功!" + userName, Toast.LENGTH_SHORT).show();
            //日志打印
            Log.i("LoginActivity", "用户注册");
        }
    }
}

三,基于回调的事件处理

        基于监听器的事件处理方法是让监听器去处理View组件产生的事件,在基于回调的事件处理机制中,事件源与事件监听器是统一的,或者说事件源本身就是事件监听器,事件源产生的事件由事件源自己去解决,解决的方法就是调用重写的回调方法。

        Android为视图组件提供了一些事件处理的回调方法,例如View类的包含:

boolean onKeyDown(int keyCode, KeyEvent event)按下按键时触发
boolean onKeyLongPress(int keyCode, KeyEvent event)长按按键时触发
boolean onKeyShortcut(int keyCode, KeyEvent event)键盘快捷键事件发生时触发
boolean onKeyShortcut(int keyCode, KeyEvent event)松开按键时触发
boolean onTouchEvent(MotionEvent event)触发触摸屏事件时触发
boolean onTrackballEvent(MotionEvent event)触发轨迹球事件时触发
void onFocusChanged(boolean gainFocus, int direction, Rect previously FocusedRect)组件焦点发生改变时触发,该方法只能在View中重写

        回调方法会接收一个MotionEvent对象,这个对象包含了触摸动作的具体信息,有以下几种常用类型:

ACTION_DOWN手指首次触摸到屏幕时触发,触发一次
ACTION_UP手指抬起时触发,触发一次
ACTION_MOVE手指在屏幕上滑动时触发,可以触发多次
ACTION_OUTSIDE触摸事件发生在视图边界时发生

        基于回调的事件处理步骤为:(1)自定义视图类继承需要的View类,(2)重写回调方法,(3)在XML文件中使用自定义的视图组件。

1.自定义视图类继承需要的View类,并重写回调方法(在实现构造方法时,必须使用两个参数的构造方法,否则app会奔溃,原因尚不清楚),回调方法返回boolean类型的值,表示是否成功解决事件,成功返回true,否则返回false。

public class MyButton extends androidx.appcompat.widget.AppCompatButton {

    //构造方法必须使用Context,AttributeSet两个参数的
    public MyButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    //重写回调方法,写入自己的逻辑
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("btn", "btn1 onTouch");
        switch (event.getAction()){
            case MotionEvent.ACTION_UP:
                Log.i("btn", "bnt1 Up");
                break;
            case MotionEvent.ACTION_DOWN:
                Log.i("btn", "bnt1 Down");
                break;
        }
        //返回是否成功解决事件
        return true;
    }
}

2.在XML文件中使用自定义的视图组件。

<com.example.practice.MyButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="按钮"
    tools:ignore="SpeakableTextPresentCheck">
</com.example.practice.MyButton>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/532565.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++题解】1601. 挖胡萝卜

问题&#xff1a;1601. 挖胡萝卜 类型&#xff1a;基本运算、小数运算 题目描述&#xff1a; 小兔朱迪挖了 x 个胡萝卜&#xff0c;狐狸尼克挖到胡萝卜数量是小兔挖到的 3 倍&#xff0c;小羊肖恩挖到胡萝卜的数量比狐狸尼克少 8 个。 请你编程计算一下狐狸尼克和小羊肖恩分别…

时间系列预测总结

转载自&#xff1a;https://mp.weixin.qq.com/s/B1eh4IcHTnEdv2y0l4MCog 拥有一种可靠的方法来预测和预测未来事件一直是人类的愿望。在数字时代&#xff0c;我们拥有丰富的信息&#xff0c;尤其是时间序列数据。 时间序列是指基于时间刻度维度&#xff08;天、月、年等&…

Mybatis plus 使用通用枚举

说明&#xff1a;mybatis plus 使用枚举可实现数据库存入时指定值保存&#xff0c; 读取时指定值展示&#xff08;返给前端&#xff09; 可通过继承IEnum<T>、 EnumValue实现 1、引包 <dependency><groupId>mysql</groupId><artifactId>mysql-…

java基础语法(16)| 集合

前言 Hello,大家好!很开心与你们在这里相遇,我是一个喜欢文字、喜欢有趣的灵魂、喜欢探索一切有趣事物的女孩,想与你们共同学习、探索关于IT的相关知识,希望我们可以一路陪伴~ 1. 集合概述 什么是集合 集合:集合是java中提供的一种容器,可以用来存储多个数据,并且可以存…

每天五分钟深度学习PyTorch:面对Tensorflow,为何我选择PyTorch

这篇专栏文章不是为了挑起tenserflow和pytorch中哪个更好&#xff0c;众所周知tensorflow诞生以来&#xff0c;已经成为最流行的深度学习框架&#xff0c;可以说github中大多数的深度学习代码实现是以tensorflow实现的&#xff0c;也就是说资源众多&#xff0c;社区强大&#x…

自动化测试十大必备(背)面试题!【含答案精讲】

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

OJ 最大奖励 C Python【贪心算法】【动态规划】

又接触到贪心算法啦&#xff0c;这道题有两种算法思路&#xff0c;我用两个语言来写了一下&#xff0c;这也涉及到了一些动态规划的思路 一.从最后一个时间枚举&#xff0c;找到在这个时间内可以完成的最大分值的题 注意点&#xff1a; 1.数组下标从1开始记录表示第几个时间…

渲染农场实时画面怎么设置?云渲染农场实时预览效果查看

许多用户在使用渲染农场服务时&#xff0c;常常难以找到查看实时渲染画面的功能。由于渲染是一个时间消耗较大的任务&#xff0c;如果最终结果与预期不符&#xff0c;可能会对整个工作流程产生负面影响。因此&#xff0c;渲染平台若能提供实时预览渲染进度和效果的功能&#xf…

冯喜运:4.10晚间黄金原油走势分析

黄金消息技术面分析&#xff1a;美国CPI年率创半年新高&#xff0c;美国3月未季调CPI年率录得3.5%&#xff0c;高于预期的3.4%水平&#xff0c;为2023年9月以来最高水平。美国CPI高于预期&#xff0c;现货黄金短线下挫16美元。日线当前的指标macd依旧属于金叉放量运行&#xff…

Spring与SpringBoot的区别

Spring是一个开源的Java应用程序框架&#xff0c;旨在简化企业级Java应用程序的开发。它提供了一个轻量级的容器&#xff0c;用于管理应用程序中的各个组件&#xff08;如依赖注入、AOP等&#xff09;&#xff0c;并提供了丰富的功能和模块&#xff0c;用于处理数据库访问、事务…

提醒|2024年CSC国家公派访问学者项目开始网申(附常见申报问题解答)

留学基金委&#xff08;CSC&#xff09;2024年国家公派高级研究学者、访问学者项目网上申报时间为4月10日—4月30日。为此&#xff0c;知识人网小编提醒申请者及时申报。本文我们将常见申报问题汇总解答&#xff0c;以帮助申请者顺利完成CSC申报工作&#xff0c;并预祝红榜题名…

python pygame事件与事件处理

本期是接上期python pygame库的略学内容最后一个步骤&#xff0c;游戏与玩家交互的内容。 一、什么是事件 游戏需要与玩家交互&#xff0c;因此它必须能够接收玩家的操作&#xff0c;并根据玩家的不同操作做出有针对性的响应。程序开发中将玩家会对游戏进行的操作称为事件&…

rk3588开发板上安装ssh服务

目的&#xff1a;实现远程访问和控制&#xff0c;其他主机远程控制rk3588 方法及操作步骤&#xff1a; 1&#xff09;安装&#xff1a;sudo apt install openssh-server 2&#xff09; 查看运行状态 sudo systemctl status ssh 其它主机远程连接该开发板的ip和端口22即可

MVP模式

1、创建数据库表单对应的实体类。 package com.mvp.model; //Model(模型)&#xff0c;数据库表单对应的实体类。 public class Word {private int id;private String engName;private String chiVal;private String lastUsedTime;private int usedTimes;private String create…

【华为笔试题汇总】2024-04-10-华为春招笔试题-三语言题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f…

uniapp 轮播列表一排展示3个,左右滑动,滑动到中间放大

一、效果展示 二、代码实现 1.html代码&#xff1a; <!-- 轮播 --><view class"heade"><swiper class"swiper" display-multiple-items3 circulartrue previous-margin1rpx next-margin1rpxcurrent0 change"swiperChange">&l…

第 6 章 Gazebo仿真环境搭建(自学二刷笔记)

6.6.4 Gazebo仿真环境搭建 到目前为止&#xff0c;我们已经可以将机器人模型显示在 Gazebo 之中了&#xff0c;但是当前默认情况下&#xff0c;在 Gazebo 中机器人模型是在 empty world 中&#xff0c;并没有类似于房间、家具、道路、树木... 之类的仿真物&#xff0c;如何在 …

SQL注入sqli_labs靶场第三题

?id1and 11 and 11和?id1and 11 and 11进行测试如果11页面显示正常和原页面一样&#xff0c;并且12页面报错或者页面部分数据显示不正常&#xff0c;那么可以确定此处为字符型注入。 根据报错信息判断为单引号带括号注入 联合查询&#xff1a; 猜解列名 ?id1) order by 3-…

微服务项目sc2024第一个子项目

1. 第一个子项目 2.pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apa…

【测试开发学习历程】python迭代、可迭代对象、迭代器、生成器

1 迭代Iteration 迭代Iteration&#xff1a;所谓迭代就是重复运行一段代码语句块的能力&#xff0c;就好比在一个容器中进行一层一层遍历数据&#xff0c;在应用过程中for循环最为突出。迭代就是从某个容器对象中逐个地读取元素&#xff0c;直到容器中没有元素为止。迭代迭代&…