一 简介
1.1 我们用的手机基本上只有一个屏幕,那这里的双屏指的什么呢?其实现在手机都是支持双屏的,我们可以在开发者选项里面来打开这个控制,来看下什么是双屏。
可以打开设置 -> 开发者选项 -> 模拟辅助显示设备来开启副屏显示,还可以选择显示尺寸
1.2 不过手机上使用双屏场景比较少,更多的用在一些人脸识别支付,或者扫码,刷卡支付这些设备设备上。
主屏用于人脸,扫码,刷卡。
副屏有键盘输入,用于输入金额,查询交易记录这些工作。
比如下面这种团餐机就是典型的双屏支持
二,双屏程序的实现
2.1 主屏,即扫码屏不用多说,正常的Activity页面。副屏(带键盘)需要借助原生API中的Presentation类
2.2 Presentation是一个特殊的 dialog ,主要的目的是在辅助显示屏上显示内容,Presentation 在创建的时候需要和特定的 Display 相关联。既是Dialog所以在构造函数中传递的 context 必须是一个 activity 的 context。
如下源码可以看出是继承于Dialog的
2.3 理解了Presentation,那后面开发就容易了,只需要用Activity控制Dialog就可以了。
但到后面你会发现还是想简单了,因为副屏是不能触摸的,这也就造成输入框不能获取焦点,软键盘不能弹出,包括返回键这些都需要通过外设设备来控制。
那这个外设设备就是小数字键盘,其实就是普通键盘的数字区域
2.4 那怎样来监听数字键盘区域的输入呢,这个时候就需要一个key的映射关系。键盘上的按键都是由标准协议的,所以我们只需要找个找个标准的映射关系就可以了。如下图
android原生api提供有键盘事件的类KeyEvent.java,里面是全部的键盘点击事件
然后我们可以在事件分发里面来监听点击的键盘哪个按键
再对照下面的code和key关系映射,就可以知道我们按的哪个键了
三,源码示例
3.1 设置权限,也可以不设置。如果想要Presentation不随主Activity退出,必须加上系统弹框权限
<!--显示系统窗口权限-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<!--在屏幕最顶部显示addview-->
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
3.2 自定义Presentation
public class SecondLoginPresentation extends Presentation {
public SecondLoginPresentation(Context outerContext, Display display) {
super(outerContext,display);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_screen);
}
}
3.3 在Acitivty里面显示这个副屏,注意这个地方要先判断是否有副屏
//显示副屏幕
SecondLoginPresentation mPresentation;
private void showDisplay() {
DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
if (presentationDisplays.length > 0) {
//判断是否有双屏
// displays[0] 主屏
// displays[1] 副屏
Display display = presentationDisplays[0];
if (mPresentation == null) {
mPresentation = new SecondLoginPresentation(this, display);
try {
mPresentation.show();
} catch (WindowManager.InvalidDisplayException e) {
mPresentation = null;
}
}
}
}
3.4 监听键盘输入,注意这个也只能在Activity里面才能监听到
只需要监听我们需要的按键即可
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (keyListener != null) {
int action = event.getAction();
switch (action) {
case KeyEvent.ACTION_DOWN:
if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) {
return super.dispatchKeyEvent(event);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {
return super.dispatchKeyEvent(event);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
return super.dispatchKeyEvent(event);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
return super.dispatchKeyEvent(event);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_HOME) {
return super.dispatchKeyEvent(event);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
return super.dispatchKeyEvent(event);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_F1) {
keyListener.textSure("功能");
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_F2) {
keyListener.textSure("设置");
return true;
} else if (event.getKeyCode() == 111 || event.getKeyCode() == 4) {
keyListener.textSure("取消");
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
keyListener.textSure("删除");
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
keyListener.textSure("确认");
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
keyListener.textSure("上箭头");
return true;
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
keyListener.textSure("下箭头");
return true;
} else {
int unicodeChar = event.getUnicodeChar();
keyListener.textChange(String.valueOf((char) unicodeChar));
return true;
}
}
}
return super.dispatchKeyEvent(event);
}
3.5 SecondLoginPresentation处理键盘事件
@Override
public void textChange(String text) {
//数字输入
addTextValue(text);
}
@Override
public void textSure(String value) {
//除数字之外按键
switch (value) {
case "功能":
break;
case "设置":
break;
case "删除":
popTextValue();
break;
case "取消":
break;
case "确认":
//开始支付逻辑
//....................................
break;
case "上箭头":
break;
case "下箭头":
break;
}
}
//输入键盘监听-添加
private Stack<String> mNumberStack = new Stack<>();
public void addTextValue(String value) {
//限制输入数字或者小数点
if (!Utils.isNumeric(value)) {
return;
}
String moneyString = etInputContent.getText().toString();
//确保第一位不是.和+
if ((value.equals(".") || value.equals("+")) && moneyString.length() <= 0) {
return;
}
//确保不输入连续的+
if (value.equals("+") && moneyString.endsWith("+")) {
return;
}
//确保不是连续小数点
if (value.equals(".") && moneyString.endsWith(".")) {
return;
}
//确保一个小数点,后面两位
//获取最后一个加号的索引
String lastPartString="";
if (moneyString.length() > 0 && moneyString.contains("+")) {
lastPartString = moneyString.substring(moneyString.lastIndexOf("+"));
}else {
//如果长度小于0表示还没输入过加号,那最后一段就是完整内容
lastPartString = moneyString;
}
if (!value.equals("+") && lastPartString.contains(".") && lastPartString.substring(lastPartString.indexOf(".")).length() > 2) {
return;
}
//确保当前段不包含两个小数点
if (value.equals(".") && lastPartString.contains(".")) {
return;
}
//限制最大金额-7位
// if (!TextUtils.isEmpty(moneyString) && moneyString.length() >= 7) {
// return;
// }
//确保第一位不为0
if (moneyString.length() == 1 && moneyString.startsWith("0") && !value.equals(".")) {
mNumberStack.clear();
}
mNumberStack.push(value);
showTextValue();
}
//输入键盘监听-删除
public void popTextValue() {
if (mNumberStack.empty()) {
return;
}
mNumberStack.pop();
showTextValue();
}
//显示输入内容
public void showTextValue() {
StringBuilder codeBuilder = new StringBuilder();
for (String value : mNumberStack) {
codeBuilder.append(value);
}
etInputContent.setText(codeBuilder.toString());
moneyInputResult();
}
//计算总金额
public void moneyInputResult() {
String inputString = etInputContent.getText().toString();
String moneyResult = "";
if (!TextUtils.isEmpty(inputString)) {
if (inputString.contains("+")) {
String[] stringsArray = inputString.split("\\+");
for (String ss : stringsArray) {
moneyResult = add(TextUtils.isEmpty(moneyResult) ? "0" : moneyResult, ss);
}
} else {
moneyResult = inputString;
}
}
etMoney.setText(moneyResult);
}
/**
* 加减法精确计算类
*/
/**
* 加法
*/
public static String add(String parms1, String param2) {
return new BigDecimal(parms1).add(new BigDecimal(param2)).toString();
}
四 总结
4.1 Presentation是一个不能触摸的Dialog,所以所有事件要监听外部设备来处理
4.2 Presentation正常情况是随Activity退出的,想要不随Activity退出,需要添加系统弹框权限文章来源:https://www.toymoban.com/news/detail-594547.html
4.3 大多情况跟dialog用法没什么区别,主要能了解键盘的映射关系即可,用键盘俩操作页面文章来源地址https://www.toymoban.com/news/detail-594547.html
到了这里,关于Android之 双屏异显控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!