昨天刚学到的知识,来记录下,客户需求是将收货地址粘贴到文本框中并识别出收件人、地址和电话(这个网上有相应接口),于是乎我想到了现在有些APP(某宝、某音、某东等等等等)在其他地方粘贴好文字之后切换回APP可以直接读取到剪贴板的内容,所以我想搞一下,下面是代码~
首先是简单的读取剪贴板中内容:
2021-12-03更新:
在ios下使用下面方法可以直接获取到剪贴板内容,亲测有效
//获取粘贴板中的文本
ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
if (data != null) {
//这里是一个剪贴板对象,调用data.text就是文本,其他的内容各位自行查看
print(data);
}
//粘贴文本
Clipboard.setData(ClipboardData(text:text));
but,用我的安卓11手机测试时读取不到内容 => 为null,后来到网上找资料说安卓10以后resumed状态下无法获取剪贴板内容;在Android 高版本上,AndroidQ 对剪切板的改动是:当应用没有获取到焦点时,无法读取剪切板内容。于是乎我找到了一位大佬的博客,他的思路是这样婶儿滴:在页面中创建一个FocusNode用于获取文本框焦点,并在initState方法中对FocusNode进行监听,当从后台切换回APP(即resumed状态)时,获取到文本框的焦点并赋值,接下来上代码:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:io';
import 'package:device_info/device_info.dart';
class TestPage extends StatefulWidget {
final arguments;
TestPage({Key key, this.arguments}) : super(key : key);
_TestPageState createState() => _TestPageState(this.arguments);
}
// 注意:WidgetsBindingObserver要一起继承
class _TestPageState extends State<TestPage> with WidgetsBindingObserver {
final arguments;
_TestPageState(this.arguments);
//FocusNode
FocusNode jkNode = new FocusNode();
//文本框controller
TextEditingController jkC = new TextEditingController();
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
//判断是否是安卓10以上设备
_judgeTen();
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
// 处于这种状态的应用程序应该假设它们可能在任何时候暂停。
case AppLifecycleState.inactive:
break;
// 应用程序可见,前台
case AppLifecycleState.resumed:
//判断平台信息
_judgePlatformInfo();
break;
// 应用程序不可见,后台
case AppLifecycleState.paused:
break;
// 申请将暂时暂停
case AppLifecycleState.detached:
break;
}
}
//判断是否是安卓10以上设备
_judgeTen () async {
//获取设备信息
DeviceInfoPlugin dip = new DeviceInfoPlugin();
AndroidDeviceInfo adi = await dip.androidInfo;
//经亲测发现安卓10以下取到的版本号是xxx.0,安卓10以上直接取到10或者11
String version = "";
if (adi.version.release.contains(".")) {
//判断版本号中是否有.,有的话用.分割一下取得那个整数(返回的是字符串类型)
var haha = adi.version.release.split(".");
version = haha[0];
} else {
version = adi.version.release;
}
//如果版本号大于等于10,则监听FocusNode
if ( int.parse(version) >= 10 ) {
_androidAboveTengetClipboardContent();
}
}
//判断平台信息
_judgePlatformInfo () async {
if (Platform.isAndroid) {
DeviceInfoPlugin dip = new DeviceInfoPlugin();
AndroidDeviceInfo adi = await dip.androidInfo;
String version = "";
if (adi.version.release.contains(".")) {
var haha = adi.version.release.split(".");
version = haha[0];
} else {
version = adi.version.release;
}
if ( int.parse(version) < 10 ) {
_androidBelowTengetClipboardContent();
} else {
FocusScope.of(context).requestFocus(jkNode);
}
}
}
//获取剪贴板内容:安卓10以下和以上两个方法
_androidBelowTengetClipboardContent () async {
ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
if (data != null) {
this.jkC.text = data.text;
}
}
_androidAboveTengetClipboardContent () async {
jkNode.addListener(() async {
if (jkNode.hasFocus) {
FocusScope.of(context).unfocus();
ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
if (data != null) {
this.jkC.text = data.text;
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("测试"),
),
body: Center(
child: TextField(
textInputAction: TextInputAction.done,
focusNode: jkNode,
controller: jkC,
onEditingComplete: (){
FocusScope.of(context).unfocus();
},
decoration: InputDecoration(
hintText: "请输入快递地址信息",
),
onChanged: (val) {
print(val);
},
),
),
);
}
}
正常状况下,当你把flutter app切到后台,到别的地方赋值文字后再切回app文本框里是有文字的了,亲测有效~
但是作者后面又有改动,是通过原生安卓插件实现的,这里我就没仔细研究了,因为只自学过flutter,安卓丝毫不动,下面是我借鉴的地址:android读取剪切板选中内容,Android 10 Flutter resume状态下读取剪切板内容_体制内生存之道的博客-CSDN博客,代码有点儿乱哈哈,各位自己归纳吧~