Flutter读取剪贴板中的内容

昨天刚学到的知识,来记录下,客户需求是将收货地址粘贴到文本框中并识别出收件人、地址和电话(这个网上有相应接口),于是乎我想到了现在有些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博客,代码有点儿乱哈哈,各位自己归纳吧~

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>