如图所示的一体机
a. 如果想对把某个按键绑定到一个activity的功能上,只需要在该activity中加一个onKeyDown的监听即可。
b. 如果想把多个按键绑定到多个activity的功能上,而且想做到方便扩展,那么本文就借助了xml配置文件来实现。
首先让所用到的activity继承BaseActivity,在BaseActivity中添加OnKeyDown事件的监听。
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean ret = false;
switch (keyCode) {
case KeyEvent.KEYCODE_CALL:
WNProperties.getInstance(this).onCallBtnClick();
ret = true;
break;
case KeyEvent.KEYCODE_BACK:
if (!WNProperties.getInstance(this).onBackBtnClick()) {
finish();
}
ret = true;
break;
case KeyEvent.KEYCODE_F1:
WNProperties.getInstance(this).onF1BtnClick();
ret = true;
break;
case KeyEvent.KEYCODE_F2:
WNProperties.getInstance(this).onF2BtnClick();
ret = true;
break;
default:
break;
}
return ret;
}
可以看到在上面的代码中我对4个键进行了监听,为什么BACK键代码不一样呢,后面再谈这个问题。下面是WNProperties的代码。
public class WNProperties {
public static WNProperties instance;
public static Context mContext;
private static Map<String, String> map_ok = new LinkedHashMap<String, String>();
private static Map<String, String> map_back = new LinkedHashMap<String, String>();
private static Map<String, String> map_f1 = new LinkedHashMap<String, String>();
private static Map<String, String> map_f2 = new LinkedHashMap<String, String>();
private static Map<String, Map<String, String>> map_key;
private static Map<String, String> map_name = new LinkedHashMap<String, String>();
public static WNProperties getInstance(Context mContext) {
if (instance == null) {
return new WNProperties(mContext);
} else {
return instance;
}
}
public WNProperties(Context mContext) {
this.mContext = mContext;
initMapKey();
initActivityName();
parseXmlFile();
}
private void initActivityName() {
map_name.put("UserLogin", "com.login.UserLoginActivity");
map_name.put("OrderEdit", "com.saleManage.order.OrderEditActivity");
map_name.put("AddAccount", "com.accout.AddAccountActivity");
map_name.put("StallEdit", "com.stall.StallEditActivity");
map_name.put("AddGoods", "com.goods.AddGoodsActivity");
map_name.put("SelectDate", "com.financial.SelectDateActivity");
}
private void initMapKey() {
map_key = new LinkedHashMap<String, Map<String, String>>();
map_key.put("KEYCODE_BACK", map_back);
map_key.put("KEYCODE_CALL", map_ok);
map_key.put("KEYCODE_F1", map_f1);
map_key.put("KEYCODE_F2", map_f2);
}
public void parseXmlFile(){
InputStream in = mContext.getResources().openRawResource(R.raw.machine);
XmlPullParserFactory factory = null;
try {
factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(in, "utf-8");
int event = parser.getEventType();
String activityName = "";
while (event != XmlPullParser.END_DOCUMENT) {
switch (event) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
String tagName = parser.getName();
if ("activity".equals(tagName)) {
int count = parser.getAttributeCount();
for (int i = 0; i < count; i++) {
String attrName = parser.getAttributeName(i);
String attrValue = parser.getAttributeValue(i);
if ("name".equals(attrName)) {
activityName = getActivityName(attrValue);
}
}
}
if ("fun".equals(tagName)) {
String keyCode = "";
int count = parser.getAttributeCount();
for (int i = 0; i < count; i++) {
String attrName = parser.getAttributeName(i);
String attrValue = parser.getAttributeValue(i);
if ("key".equals(attrName))
keyCode = attrValue;
}
String funName = parser.nextText();
if (map_key.containsKey(keyCode)){
Map<String, String> map = map_key.get(keyCode);
map.put(activityName, funName);
}
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private String getActivityName(String attrValue) {
String ret = "";
if (map_name != null && map_name.containsKey(attrValue)){
ret = map_name.get(attrValue);
}
return ret;
}
public boolean onBtnClick(Map<String, String> map){
boolean ret = false;
Class mClass = mContext.getClass();
try {
String funcName = getProperties(mContext.getClass().getName(), map);
Method method = mClass.getDeclaredMethod(funcName);
method.invoke(mContext);
ret = true;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return ret;
}
public void onCallBtnClick(){
onBtnClick(map_ok);
}
public boolean onBackBtnClick(){
return onBtnClick(map_back);
}
public void onF1BtnClick(){
onBtnClick(map_f1);
}
public void onF2BtnClick(){
onBtnClick(map_f2);
}
public String getProperties(String className, Map<String, String> map) {
String ret = "";
if (map != null && map.containsKey(className)){
ret = map.get(className);
}
return ret;
}
}
WNProperties 的构造函数中,初始化map_key,初始化map_name,读取xml文件。先放上xml文件再细致讲解。
<?xml version="1.0" encoding="UTF-8"?>
<activitylist>
<activity name = "UserLogin" description = "登录页">
<fun key="KEYCODE_CALL">onLoginClick</fun>
<fun key="KEYCODE_BACK">onBackBtnClick</fun>
</activity>
<activity name = "OrderEdit" description = "开单页">
<fun key="KEYCODE_CALL">save</fun>
<fun key="KEYCODE_BACK">onBackBtnClick</fun>
</activity>
<activity name = "AddAccount" description = "添加账户页">
<fun key="KEYCODE_CALL">examAccount</fun>
</activity>
<activity name = "StallEdit" description = "编辑档口页">
<fun key="KEYCODE_CALL">save</fun>
</activity>
<activity name = "AddStaffPage" description = "添加员工页">
<fun key="KEYCODE_CALL">commitEditData</fun>
</activity>
<activity name = "AddGoods" description = "添加商品页">
<fun key="KEYCODE_CALL">saveGoodsInfo</fun>
</activity>
<activity name = "SelectDate" description = "日期选择页">
<fun key="KEYCODE_CALL">onSaveBtnClick</fun>
</activity>
</activitylist>
在parseXmlFile()方法中解析到<fun key="" />中key的值,继而判断map_key中是否含有当前的key值,如果有,拿到当前的value(也就是对应的map),把解析出的activity的名字作为key,方法作为value,存进去。
举个例子来说,读取这一条
<activity name = "UserLogin" description = "登录页">
<fun key="KEYCODE_CALL">onLoginClick</fun>
<fun key="KEYCODE_BACK">onBackBtnClick</fun>
</activity>
map_key中包含"KEYCODE_CALL"这个key,从而往map_ok中加入一条记录:key: com.login.UserLoginActivity ,value: onLoginClick。
map_key中包含"KEYCODE_BACK"这个key,从而往map_back中加入一条记录:key: com.login.UserLoginActivity ,value: onBackBtnClick。
比如这时,在LoginActivity中按下打电话按钮时,处理的流程是这样的。
WNProperties的onCallBtnClick(),执行onBtnClick(map_ok)方法,map_ok中存的值,key都是activity名字,value都是方法的名字。然后利用发射就可以执行对应的方法onLoginClick()了。要注意该方法应该是public否则不能被访问到。
这样写的代码,可以很方便扩展,如果产品需要在很多页面加很多按键的监听,写个xml文件稍作改动就行,而且xml文件可以写的足够清晰,供自己和产品观看。
最后,上面提到了在onKeyDown()里面,KEYCODE_BACK的代码和其他的不一样,这样做的原因是什么呢。
因为个别页面,按下回退键,想走自己的逻辑,大部分页面都是“关闭此页面”的逻辑,如果每个页面都配置一下挺麻烦,这样写就会方便一些,当然还有其他的方法,这里只是一种写法。
以上。·