Android之 双屏异显控制

这篇具有很好参考价值的文章主要介绍了Android之 双屏异显控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 简介

1.1 我们用的手机基本上只有一个屏幕,那这里的双屏指的什么呢?其实现在手机都是支持双屏的,我们可以在开发者选项里面来打开这个控制,来看下什么是双屏。

可以打开设置 -> 开发者选项 -> 模拟辅助显示设备来开启副屏显示,还可以选择显示尺寸

android双屏异显,android

 1.2 不过手机上使用双屏场景比较少,更多的用在一些人脸识别支付,或者扫码,刷卡支付这些设备设备上。

主屏用于人脸,扫码,刷卡。

副屏有键盘输入,用于输入金额,查询交易记录这些工作。

比如下面这种团餐机就是典型的双屏支持

android双屏异显,android

 二,双屏程序的实现

2.1 主屏,即扫码屏不用多说,正常的Activity页面。副屏(带键盘)需要借助原生API中的Presentation类

2.2 Presentation是一个特殊的 dialog ,主要的目的是在辅助显示屏上显示内容,Presentation 在创建的时候需要和特定的 Display 相关联。既是Dialog所以在构造函数中传递的 context 必须是一个 activity 的 context。

如下源码可以看出是继承于Dialog的

android双屏异显,android

 2.3 理解了Presentation,那后面开发就容易了,只需要用Activity控制Dialog就可以了。

但到后面你会发现还是想简单了,因为副屏是不能触摸的,这也就造成输入框不能获取焦点,软键盘不能弹出,包括返回键这些都需要通过外设设备来控制。

那这个外设设备就是小数字键盘,其实就是普通键盘的数字区域

android双屏异显,android

2.4 那怎样来监听数字键盘区域的输入呢,这个时候就需要一个key的映射关系。键盘上的按键都是由标准协议的,所以我们只需要找个找个标准的映射关系就可以了。如下图

android原生api提供有键盘事件的类KeyEvent.java,里面是全部的键盘点击事件

android双屏异显,android

 然后我们可以在事件分发里面来监听点击的键盘哪个按键

android双屏异显,android

 再对照下面的code和key关系映射,就可以知道我们按的哪个键了

android双屏异显,android

 三,源码示例

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退出,需要添加系统弹框权限

4.3 大多情况跟dialog用法没什么区别,主要能了解键盘的映射关系即可,用键盘俩操作页面文章来源地址https://www.toymoban.com/news/detail-594547.html

到了这里,关于Android之 双屏异显控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第二节-安卓多屏双屏实战车载车机智能驾驶舱开发/千里马android framwork开发

    hi,粉丝朋友们! 上一节已经对车载的多屏互动进行了相关的技术方案介绍,以及相关的核心方法 moveRootTaskToDisplay的讲解和使用。 具体可以参考链接:https://blog.csdn.net/learnframework/article/details/130461689 本节就来进行代码实战 要实现双屏互动,主要就只需要两个步骤: 1、手指动

    2024年02月09日
    浏览(50)
  • android app控制ros机器人三(android登录界面)

    接下来是二次开发的具体环节了,由于存在用户需求,用到ros-mobile不多,更偏向于android开发。 用ppt画了简单的展示界面,与用后交流界面的功能布局。先开发一代简易版本的app,后续可以丰富完善。ctrlc+v上线。 登录界面--在ros-mobile基础上增加登录界面,初代版本只设置登

    2024年02月14日
    浏览(94)
  • msf使用木马控制android手机

    msf使用木马控制android手机 kali、手机模拟器(或不用的手机)。 手机模拟器(或者手机)与电脑可以互相连通吗,即手机可以直接访问到kali。 命令:msfvenom -p android/meterpreter/reverse_tcp lhost=192.168.32.135 lport=4444 android_shell.apk ; 2、手机安装木马。 想办法把木马放到手机模拟器(

    2024年02月10日
    浏览(42)
  • Android 动态控制view的大小

    这样就实现了控件尺寸随着我们手指滑动变化了。 OnTouchListener中有event.getX(),event.getY(),和event.getRawX(),event.getRawY(),他们究竟有什么区别了? getX和getY代表相当于控件本身的位置,getRawX和getRawY相对屏幕的位置

    2023年04月08日
    浏览(103)
  • Android Studio 的版本控制Git

    Android Studio 的版本控制Git。 Git 是最流行的版本控制工具,本文介绍其在安卓开发环境Android Studio下的使用。 本文参考链接是:https://learntodroid.com/how-to-use-git-and-github-in-android-studio/ 一:Android Studio 中设置Git  1:下载Git 我的本来就有,就不要下载了,如果你的没有,那你就要

    2024年02月14日
    浏览(35)
  • 【Android】-- 如何对APP版本控制/更新?

    目录 一、 前提准备 1、获取服务器 2、使用工具操作云服务器  二、Json格式网页  三、创建file_paths.xml及修改AndroidManifest.xml 四、在java代码加入更新检测代码 效果如图:         可以强制更新和非强制更新,和浏览器下载安装包。         首先去获取云服务器,如:阿

    2024年02月12日
    浏览(40)
  • Android Studio Giraffe控制台乱码

    这几天在使用Android Studio Giraffe进行一个App的开发,在项目构建的时候,控制台输出中文都是乱码,看着很不爽,进行了两项配置,中文就可以正常输出了,看起来就爽多了。 第一个配置:点击Help菜单下的Edit Custom VM Options…选项卡,在文件中添加“-Dfile.encoding=UTF-8”保存。

    2024年02月12日
    浏览(43)
  • android app控制ros机器人一

    android开发app,进而通过控制ros机器人,记录开发过程 查阅资料: rosjava使用较多,已经开发好的app也有开源的案例 rosjava · GitHub https://github.com/ros-autom/RobotCA https://github.com/ROS-Mobile/ROS-Mobile-Android https://github.com/ros-android/android_app_manager GitHub - ros-android/android_sensors_driver: ROS Driv

    2024年02月15日
    浏览(41)
  • Android MQTT:实现设备信息上报与远程控制

    1.1 MQTT是什么? MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,最初由IBM开发,用于连接远程设备与服务器之间的通信。它在物联网(IoT)应用中变得越来越流行,因为它具有以下特点: 轻量级协议 :MQTT是一种精简的协议,有效地减少了通信开销,适合于

    2024年02月09日
    浏览(41)
  • android app控制ros机器人五(百度地图)

    半吊子改安卓,新增了标签页,此标签页需要显示百度地图 按照官方教程注册信息,得到访问应用AK,步骤也可以参照下面csdn Android地图SDK | 百度地图API SDK 【Android】实现百度地图显示_宾有为的博客-CSDN博客 本人使用的是aar开发包,ros-mobile工程中app下没有libs文件夹需要新建

    2024年02月13日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包