Android开发秘籍学习笔记(十)

本文介绍了Android开发中如何截取物理按键事件并构建菜单的方法。包括标准物理按键的触发事件及回调方法,如onKeyUp、onKeyDown等,并详细解释了它们的作用及应用场景。此外,还介绍了如何创建选项菜单、上下文菜单和子菜单。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  该目录为Android开发秘籍学习笔记关于截取物理按键事件和构建菜单

截取物理按键事件:

  标准Android设备拥有多个可以触发事件的物理按键,如下:
Android常用的物理按键及其触发事件 KEYCODE_POWER 电源键 KEYCODE_MENU 菜单键 KEYCODE_BACK 后退键
 * KEYCODE_HOME Home键 KEYCODE_CAMERA 相机键 KEYCODE_SEARCH 查找键 KEYCODE_VOLUME_UP
 * 音量键+ KEYCODE_VOLUME_DOWN 音量键- KEYCODE_VOLUME_MUTE 静音 方向键 KEYCODE_DPAD_CENTER
 * KEYCODE_DPAD_UP KEYCODE_DPAD_DOWN KEYCODE_DPAD_LEFT KEYCODE_DPAD_RIGHT 键盘键
 * 数字0~9 字母A~Z KEYCODE_0 ~ KEYCODE_9 KEYCODE_A ~ KEYCODE_Z 提供的回调方法有
<span style="font-family:Microsoft YaHei;font-size:14px;"> * onKeyUp()、OnKeyDown()、onKeyLongPress()</span>
  系统首先会将KeyEvent发送给当前获得焦点的Activity或视图中适宜的回调方法,下面给出这些回调方法。
  • onKeyUp()、onKeyDown()、onKeyLongPress():物理按键按下的回调方法。
  • onTrackballEvent()、onTouchEvent():轨迹球及触屏操作的回调方法。
  • onFoucsChanged():视图获得或失去焦点时的回调方法。
  这里给出例子:
/**
	 * 重写onKeyDown方法可以拦截系统默认的处理
	 */

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODOAuto-generated method stub
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Toast.makeText(this, "后退键", Toast.LENGTH_SHORT).show();
			return true;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
			Toast.makeText(this, "声音+", Toast.LENGTH_SHORT).show();
			return false;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
			Toast.makeText(this, "声音-", Toast.LENGTH_SHORT).show();
			return false;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
			Toast.makeText(this, "静音", Toast.LENGTH_SHORT).show();
			return false;
		} else if (keyCode == KeyEvent.KEYCODE_HOME) {
			Toast.makeText(this, "Home", Toast.LENGTH_SHORT).show();
			return true;
		}// 电源键和Home键是系统截获的,不会触及应用程序的自定义
		return super.onKeyDown(keyCode, event);
	}

	/**
	 * 重写onTouchEvent方法可以处理Touch事件
	 */

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		if (event.getAction() == MotionEvent.ACTION_MOVE) {
			Toast.makeText(this, "ACTION_MOVE", Toast.LENGTH_SHORT).show();
		} else if (event.getAction() == MotionEvent.ACTION_UP) {
			Toast.makeText(this, "ACTION_UP", Toast.LENGTH_SHORT).show();
		} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
			Toast.makeText(this, "ACTION_DOWN", Toast.LENGTH_SHORT).show();
		}
		return super.onTouchEvent(event);
	}
  在代码中,大家可以发现onKeyDown()中有的物理按键事件return true;有的return false;倘若return true则是把事件“消耗”(consume)掉,即让它本来的功能失去掉。比如上面的KeyEvent.KEYCODE_BACK本来是要执行finish()操作的,但是你按手机上的BACK键,它并不会执行finish()。因为它被“消耗”掉了。因为事件被消耗掉了以后,就不会传递给其他Android组件了,但有几个例外。
  • 电源键和HOME键是由系统截获的,不会触及应用程序的自定义。
  • 对后退键、菜单键、HOME键和搜索键不应拦截KeyDown事件,而应该拦截KeyUp。这点与Android2.0的建议一致,因为在某些平台上这些按钮不见得是真实的物理按键。所以上例中点击HOME键,即使是return true,它仍然会退回到主屏幕。

构建菜单:

 
  在Android中,开发者可以实现三种类型的菜单----选项菜单,上下文菜单,子菜单。
  •   选项菜单:Activity的主菜单,当按下菜单键时就会显示出来。对于Android API level 10或者更低版本,它包含一个图标菜单(icon menu),还可能包含一个会在“更多”菜单项被选中时弹出的扩展菜单(extended menu)。较新的Android版本只有原始的选项菜单。
  • 上下文菜单:一个浮动的菜单项列表,当长按某个视图时出现。
  • 子菜单:一个浮动菜单项列表,当某个菜单项被选中时会出现。
  菜单构建的一个例子:
import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private final int MENU_ADD = 1, MENU_SEND = 2, MENU_DEL = 3;
	private final int GROUP_DEFAULT = 0, GROUP_DEL = 1;
	private final int ID_DEFAULT = 0;
	private final int ID_TEXT1 = 1, ID_TEXT2 = 2, ID_TEXT3 = 3;
	private String[] choices = { "Press me", "Try again", "Change me" };

	private static int itemNum = 0;
	private static TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		tv = (TextView) findViewById(R.id.tv);

		registerForContextMenu(tv);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(GROUP_DEFAULT, MENU_ADD, 0, "ADD").setIcon(
				R.drawable.ic_launcher);
		menu.add(GROUP_DEFAULT, MENU_SEND, 0, "Send");
		menu.add(GROUP_DEFAULT, MENU_DEL, 0, "Delete");
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case MENU_ADD:
			create_note();
			return true;
		case MENU_SEND:
			send_note();
			return true;
		case MENU_DEL:
			delete_note();
			return true;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	private void delete_note() {
		itemNum--;
	}

	private void send_note() {
		Toast.makeText(this, "ItemNum:" + itemNum, Toast.LENGTH_SHORT).show();
	}

	private void create_note() {
		itemNum++;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		if (itemNum > 0) {
			menu.setGroupVisible(GROUP_DEL, true);
		} else {
			menu.setGroupVisible(GROUP_DEL, false);
		}
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		if (v.getId() == R.id.tv) {
			SubMenu textMenu = menu.addSubMenu("Change Text");
			textMenu.add(0, ID_TEXT1, 0, choices[0]);
			textMenu.add(0, ID_TEXT2, 0, choices[1]);
			textMenu.add(0, ID_TEXT3, 0, choices[2]);

			menu.add(0, ID_DEFAULT, 0, "Original TEXT");
		}
		super.onCreateContextMenu(menu, v, menuInfo);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		return super.onContextItemSelected(item);
	}
}
  这个例子把所有的菜单类型全部包括进去了。下面就解析下这个例子----onCreateOptionsMenu()方法只被调用一次,在Activity的其他部分不需要被再次构。然而,如果在运行时需要改变任意菜单选项,可以随时调用onPrepareOptionMenu()方法。如果选项菜单中的某一项被点击,onOptionsItemSelected()方法会被调用。调用时会传递选中的菜单项的ID,可以使用switch语句来确定被选中的选项是哪个。接下来就是Menu.add()这个函数了
public abstract MenuItem add (int groupId, int itemId, int order, CharSequence title) 
Added in API level 1
Add a new item to the menu. This item displays the given title for its label.

Parameters
groupId  The group identifier that this item should be part of. This can be used to define groups of items for batch state changes. Normally use NONE if an item should not be in a group. 
itemId  Unique item ID. Use NONE if you do not need a unique ID. 
order  The order for the item. Use NONE if you do not care about the order. See getOrder(). 
title  The text to display for the item. 

Returns
The newly added menu item. <span style="color:#ff0000;">
</span>
  可以看到add()方法的第一个参数为菜单项组设定名字标签。同一组中的菜单项可以被一起处理。第二个参数是代表菜单项的整型ID号,它被传递给回调函数,以确定哪个菜单项被选中。第三个参数是菜单中项目的顺序。如果不给定该参数,则按项目被添加到Menu对象上的次序来决定项目的顺序。最后一个参数是菜单项显示的文本,该参数可以是一个String型变量或是一个项R.String.mylabel这样的字符串源。接下来就是上下文菜单了,可以在onCreate()中看到registerForContextMenu(tv);这是为某个视图注册一个上下文菜单(Context Menu),当该视图被长按时,会调用onCreateContextMenu来建立上下文菜单。此处通过addSubMenu()方法来为Menu实例实现SubMenu。子菜单项随主菜单项一同被指定,无论哪个菜单中的选项被选中,都会调用onContextItemSelected()方法。

  效果图:
 
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值