android事件处理主要方法,Android-事件处理与内部通信

程序猿的开心一刻###

以下谁是二进制思想的最早提出者?

a,伏羲;b,姬昌;c,莱布尼茨;d,柏拉图。

请在评论区输入答案,接下来进入正题

一、简介

本文将带你学习Android中最基本的事件处理机制,了解什么是事件,怎样来监听事件。随后你将学习到什么是意图,以及通过一个实例来学习怎样用意图在Activity间传递信息。

知识点

Android事件监听器

Android事件处理者

事件监听器的注册

在Activity之间传递数据

二、事件处理

对于应用的交互而言,事件是一个收集用户交互信息的有效途径。这些事件包括按压按钮或者触碰屏幕。Android的框架维护了一个基于先进先出的事件队列,你可以在程序中捕获这些事件,并针对每个需求,采取合适的行动。

下面有三个关于Android事件管理的概念:

事件监听器:事件监听器是View类中的一个接口,它包含了一个回调方法。当用户与UI组件进行交互时,相应已注册的监听器会被触发,Android框架会调用这些方法。

事件监听器注册:事件注册就是一个事件处理者通过事件监听器来注册的过程。因此,事件监听器触发事件时调用响应的处理者(Handler)。

事件处理者:当某个事件发生时,如果我们为该事件注册了一个事件监听器,那么这个监听器就会调用事件处理者。后者为实际处理该事件的方法。

1. 事件监听器和事件处理者

以下为一些常见的事件处理者,后面补充了它对应的事件监听器和说明。

onClick():对应的事件监听器是OnClickListener()。当用户点击、触摸或者聚焦(给它焦点)与任何一个部件时(这些部件有按钮、文本和图片等),该方法就会被调用。你可以使用名为onCLick()的事件处理者来处理这些事件。

onLongClick():对应的事件监听器是OnLongClickListener()。当用户长时间(一秒或者很多秒)点击、触摸或聚焦于任何一个部件时,该方法会被调用。你可以使用名为onLongClick()的事件处理者来处理这些事件。

onFocusChange():对应的事件监听器是OnFocusChangeListener()。有时当用户从某个视图部件上移开关注时,这个部件就会失去焦点,此时该方法会被调用。你可以使用onFocusChange()这个事件处理者来处理这些事件。

onKey():对应的事件监听器是OnFocusChangeListener。当用户关注某个部件并且按压(或释放)了设备上的实体按键时,该方法会被调用。你可以使用onKey()事件处理者来处理这个事件。

onTouch():对应的事件监听器是OnTouchListener()。当用户按键、释放按键或者在屏幕上任意移动手势时,会调用该方法。你可以使用onTouch()事件处理者来处理这个事件。

onMenuItemClick:对应的事件监听器是onMenuItemCLickListener()。当用户选择了一个菜单项时会调用该方法。你可以使用onMenuItemCLick()事件处理者来处理这个事件。

onCreateContextMenu():对应的事件监听器是OnCreateContextMenuItemListener()。当上下文菜单正在建立时(持续的长按动作会触发该事件)会调用该方法。

在View类中,还有更多诸如OnHoverListener、OnDragListener之类的事件监听器可供使用。所以为了开发具有更加丰富功能的应用,你需要去查阅和参考Android开发的官方文档。

2. 事件监听器注册

前文提到过,事件的注册就是一个事件处理者注册事件监听器的过程。尽管对于注册监听器来说,有许多灵活的方法,但在本文中只列出了其中最常用的3种方法。在你的实际项目中,可以任意使用其中之一。

这些方法有:

使用匿名内部类

在Activity类中实现Listener的接口。

在activity_main.xml(对应的)布局文件中直接通过android:onClick属性指定事件处理者。

下面的内容将为你逐一讲解。

(1)使用匿名内部类注册事件监听器

以按钮的点击事件为例,首先要在xml布局文件中定义按钮的id,然后在Activity类中实例化控件,使用自定义的内部类,如下所示:

public class MainActivity extends Activity{

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 此处写其他代码

// button是查找后赋值的按钮对象

button.setOnClickListener(new MyOnClickListener();

}

// 自定义的匿名内部类

Private final class MyOnClickListener implements OnClickListener{

Public void onClick(View view){

// 此处写点击功能的逻辑

}

}

}

(2)实现事件监听器接口

这种方法是让当前Activity实现OnClickListener,并实现这个接口中的方法:onClick(View view):

public class MainActivity extends Activity implements OnClickListener{

// 当然这儿应该还有该类中的其他内容

@Override

Public void onClick(View view){

// 此处填实现的细节

}

}

(3)在布局文件中指定事件处理者

以按钮的点击事件为例,这种方法是在xml布局文件中,在控件属性里添加android:onClick属性,然后指明调用方法的名字,例如android:onClick="onAddClick"。

在对应的Activity类中,也需要写一个对应的方法,方法名要与之对应,如:

public void onAddClick(View view){

//这里填具体的逻辑

}

3. 触碰模式

用户可以通过实体按键、屏幕上的按钮,以及触摸屏幕来和设备交互。触摸屏幕能让设备进入触碰模式,用户可以通过屏幕上的虚拟按钮、图片来完成交互。你可以通过调用View类的isInTouchMode()方法来检查设备是否处于触碰模式。

这个流程图如下所示:

wm

此处输入图片的描述

4. 焦点

一个视图或部件在处于获得焦点状态时,通常会高亮显示或者显示一个闪烁的光标。这个状态意味着它已经准备好去接收用户的输入。

所以对于状态,主要的检查方法如下:

isFocusable():返回true或者false。

isFocusableInTouchMode():检查某个组件(或视图)在触碰模式下是否可以获得焦点(当使用实体按键但设备不处于触碰模式时,一个视图仍然是可以获得焦点的)。

在XML文件中可以对这些组件设置如下的属性,以确定是哪个组件可以获得焦点:

android:focusUp="@+id/组件的ID"

5. 触碰事件onTouchEvent()

对于触碰事件的处理方式如下,请尝试去阅读代码块:

public boolean onTouchEvent(motionEvent event){

// 通常需要重写这个onTouchEvent()方法来对指定的操作实现响应

switch(event.getAction()){

// 对event对象传入的多个动作,使用getAction()方法获得该动作的ID值(均是预定义好的常量),

// 然后进行比较,在一些判断中来执行后续的操作。

// 本例使用了switch,你可以根据实际情况选择if、while并进行条件判断。

case TOUCH_DOWN:

//TOUCH_DOWN指代了用户的手指已经按到屏幕上但还未抬起的这一动作。

Toast.makeText(this,"The Button has been clicked down.",Toast.LENTH_LONG).show();

//此处用了一个Toast提示框来显示用户执行了何种操作,下同。

break();

case TOUCH_UP:

//TOUCH_UP指代了用户的手指从屏幕上抬起的这一动作。

Toast.makeText(this,"The Button has been clicked up.",Toast.LENTH_LONG).show();

break;

case TOUCH_MOVE:

//TOUCH_MOVE指代了用户的手指在屏幕上移动但还未抬起的这一动作。

Toast.makeText(this,"The Button has been clicked move."Toast.LENTH_LONG).show();

break;

}

return super.onTouchEvent(event) ;

}

三、内部通信

当某个Activity需要启动另外一个Activity时,对于用于来说表现的是操作界面的切换,而对于应用本身来说,则需要通过意图(Intent)来告诉系统自己想要启动哪个Activity。

事实上,无论是启动一个Activity还是一个Service,或者一个BroadcastReceiver,在Android中均需要用Intent来封装这种调用的“意图”。

而在这些组件切换的过程中,就可以使用Intent来传递信息。你可以将数据封装成Bundle对象,然后用Intent把这个对象携带至其他地方,从而实现了系统内部的一次数据交换。

以后经常会用到startActivity(Intent intent)、startService(Intent service)和sendBroadcast(Intent intent)等方法,这些方法就是使用了Intent来启动不同的组件。

现在我们主要讨论Intent操作Activity的相关知识。

意图是对于将要执行的操作的抽象描述。在startActivity()方法中,可以用意图来启动一个Activity。意图的本身是一个Intent对象,它是一个可传递的数据结构,存放了将要执行的操作的抽象描述。

例如,你在某个Activity中需要打开邮件客户端并使用设备来发送给一封电子邮件,那么在你的Activity中就要用合适的选择器,发送一个ACTION_SEND意图给意图解析器。指定的选择器将给予用户合适的接口,让他选择怎样发送电子邮件数据(这一步有点类似于Windows系统中的打开方式,但它们并不是同一类东西)。

实现这个功能的主要代码如下:

Intent intent_sendEmail = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));

email.putExtra(Intent.EXTRA_EMAIL, 收件人的地址);

email.putExtra(Intent.EXTRA_SUBJECT, 邮件“主题”);

email.putExtra(Intent.EXTRA_TEXT, 邮件“正文”);

startActivity(Intent.createChooser(intent_sendEmail, "请选择一个邮件客户端以发送电子邮件…"));

再比如,假设你需要一个Activity来打开设备上的浏览器应用并访问指定的URL,你就需要在Activity中发送一个ACTION_WEB_SEARCH意图给Android意图解析器,从而在浏览器中打开这个URL。

意图解析器解析了众多的Activity,并且选中最适合当前设定的那一个(例如本例中的浏览器Activity),然后意图解析器会将网页的URL传递给浏览器并访问它。

实现该功能的代码样例如下:

String keyword = "阿里巴巴";

Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);

intent.putExtra(SearchManager.QUERY, keyword);

startActivity(intent);

上面这段代码会在Android的搜索引擎中搜索shiyanlou相关信息。

对于在Activity中传递信息而言,则需要使用到Bundle。我们稍后在实例中为你讲解其详细的使用方法。

四、实例

下面通过一个实例,通过实现匿名类和XML中声明两种方法来注册事件监听器。

主要有以下步骤:

请使用Android Studio来创建一个项目。

除了MainActivity,请通过菜单再创建一个名为SecondActivity的Activity。

在res/layout/activity_main.xml文件中的布局里,为MainActivity添加两个主要的控件:一个文本框EditText、一个按钮Button,并设置它们的属性(详细代码请参考后文)。

在res/layout/activity_second.xml文件中的布局里,为SecondActivity添加两个主要的控件:一个按钮Button和一个文本标签TextView,并设置它们的属性(详细代码请参考后文)。特别注意在按钮的属性中添加一个android:onClick="show"来注册监听器。

修改MainActivity.java文件,在MainActivity类中声明刚刚添加的控件,在onCreate()方法内对它们进行实例化(使用findViewById()方法),对按钮以匿名内部类的方式添加点击事件监听器,在onClick方法中获取文本框的输入值,通过Bundle对象存入Intent,并以这个Intent对象启动SecondActivity。

修改SecondActivity.java文件中,实现已注册的show方法,在其中获取MainActivity传过来的值,并显示在TextView中。

检查代码,编译并运行这个应用,在模拟器中查看运行的过程,检查其是否与设计的相一致。

下面是部分要用到的代码:

首先是res/layout/activity_main.xml中的内容:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.example.work.eventtest.MainActivity">

android:layout_width="match_parent"

android:layout_height="60dp"

android:id="@+id/editText01"

android:layout_marginTop="20dp"

android:textSize="20sp"

android:background="@color/colorAccent"/>

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_below="@id/editText01"

android:layout_marginTop="50dp"

android:id="@+id/button1"

android:background="@color/colorPrimaryDark"

android:text="发送文本"/>

接下来是MainActivity.java中的内容,建议你先按照自己的思路实现,再来通过下面的代码验证自己的想法:

package com.example.work.eventtest;

import android.content.Intent;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

private Button button;

private EditText editText;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//实例化控件

button = (Button) findViewById(R.id.button1);

editText = (EditText)findViewById(R.id.editText01);

// 通过匿名内部类来为button注册点击事件监听器

button.setOnClickListener(new View.OnClickListener() {

// 重写onCLick()方法,实现点击事件处理者的功能

@Override

public void onClick(View v) {

// 创建一个字符串对象用于接收来自文本框的输入内容

String message = new String();

// 通过文本框的getText()方法获取输入内容,赋予message字符串对象

message = editText.getText().toString();

// 创建一个“意图”,用于从MainActivity跳转到SecondActivity

Intent intent = new Intent(MainActivity.this,SecondActivity.class);

// 创建一个Bundle对象,名为data,用于在Activity之间传递信息

Bundle data = new Bundle();

// 向这个Bundle对象中存入内容,因为是字符串,所以用putString()方法

// 参数的形式是key-value形式,在另外一个Activity取出内容的时候就是通过这个key

// 如果是其他的内容,则根据不同的数据类型选用不同的存入方法

data.putString("mA",message);

// 最后将Bundle存入intent对象中,让后者携带到另外一个Activity中

intent.putExtras(data);

// 调用startActivity()方法,跳转到另外一个Activity

startActivity(intent);

// 如果你想在启动SecondActivity的过程中关闭现在这个Activity,

// 则可以使用finish()方法来结束当前Activity。

// MainActivity.this.finish();

}

});

}

}

接下来再创建一个SecondActivity,下面是res/layout/activity_second.xml中的内容。

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/activity_second"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ff00ff"

tools:context="com.example.work.eventtest.SecondActivity">

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_marginTop="30dp"

android:background="#00aaee"

android:textSize="20sp"

android:id="@+id/textview1"/>

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_below="@id/textview1"

android:layout_marginTop="50dp"

android:background="#aa00e0"

android:text="显示传过来的文本"

android:onClick="show"

android:id="@+id/button2"/>

以下是SecondActivity.java中的内容,在这里面我们就没有注册按钮的点击事件监听器了,而是实现了一个show()方法用于承担点击事件处理者的职责。

package com.example.work.eventtest;

import android.content.Intent;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.TextView;

public class SecondActivity extends AppCompatActivity {

// 声明一个文本标签控件

private TextView textView;

// 声明一个字符串变量用于存放前一个Activity中传过来的信息

private String message;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_second);

// 实例化这个文本标签

textView = (TextView)findViewById(R.id.textview1);

// 通过getIntent()方法来获得启动当前Activity的上一个Intent对象

Intent intent = getIntent();

// 从intent对象中通过getExtras()方法获得其携带的消息,

// 接下来调用getString()方法来得到这个字符串,注意该方法的参数为(字符串的key,默认值)

message = intent.getExtras().getString("mA","null");

}

public void show(View view){

// 如果获得了上个Activity传过来的消息,则显示在TextView中

if(message!=null){

textView.setText(message);

}

}

}

检查一下代码,编译并运行这个应用。等待应用安装至模拟器后,你会看到如下的画面:

747f26fc9325

演示.gif

参考文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值