如何在 Flutter 中制作可复制的 Text Widget?

How to make copyable Text Widget in Flutter?

Text widget 上长按 Tab 键时,工具提示会显示 'copy'。单击 'copy' 时,文本内容应复制到系统剪贴板。

下面长按会复制文本,但不会显示'copy',所以用户不会知道,内容已复制到剪贴板。

class CopyableText extends StatelessWidget {
  final String data;
  final TextStyle style;
  final TextAlign textAlign;
  final TextDirection textDirection;
  final bool softWrap;
  final TextOverflow overflow;
  final double textScaleFactor;
  final int maxLines;
  CopyableText(
    this.data, {
    this.style,
    this.textAlign,
    this.textDirection,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
  });
  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      child: new Text(data,
          style: style,
          textAlign: textAlign,
          textDirection: textDirection,
          softWrap: softWrap,
          overflow: overflow,
          textScaleFactor: textScaleFactor,
          maxLines: maxLines),
      onLongPress: () {
        Clipboard.setData(new ClipboardData(text: data));
      },
    );
  }
}

您可以使用 SnackBar 通知用户复制。

这里有一个相关的代码:

String _copy = "Copy Me";

  @override
  Widget build(BuildContext context) {
    final key = new GlobalKey<ScaffoldState>();
    return new Scaffold(
      key: key,
      appBar: new AppBar(
        title: new Text("Copy"),
        centerTitle: true,
      ),
      body:
      new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new GestureDetector(
              child: new Text(_copy),
              onLongPress: () {
                Clipboard.setData(new ClipboardData(text: _copy));
                key.currentState.showSnackBar(
                    new SnackBar(content: new Text("Copied to Clipboard"),));
              },
            ),
            new TextField(
                decoration: new InputDecoration(hintText: "Paste Here")),
          ]),


    );
  }

编辑

我正在做某事并且做了以下工作,所以我想到重新审视这个答案:

import "package:flutter/material.dart";
import 'package:flutter/services.dart';

void main() {
  runApp(new MaterialApp(home: new MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  String _copy = "Copy Me";

  @override
  Widget build(BuildContext context) {
    final key = new GlobalKey<ScaffoldState>();
    return new Scaffold(
      key: key,
      appBar: new AppBar(
        title: new Text("Copy"),
        centerTitle: true,
      ),
      body:
      new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new GestureDetector(
              child: new CustomToolTip(text: "My Copyable Text"),
              onTap: () {

              },
            ),
            new TextField(
                decoration: new InputDecoration(hintText: "Paste Here")),
          ]),


    );
  }
}

class CustomToolTip extends StatelessWidget {

  String text;

  CustomToolTip({this.text});

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      child: new Tooltip(preferBelow: false,
          message: "Copy", child: new Text(text)),
      onTap: () {
        Clipboard.setData(new ClipboardData(text: text));
      },
    );
  }
}

从 Flutter 1.9 开始,您可以使用

SelectableText("Lorem ipsum...")

选择文本后,将出现 "Copy" 上下文按钮。

SelectableText(
  "Copy me",
  onTap: () {
    // you can show toast to the user, like "Copied"
  },
)

如果您想为文本设置不同的样式,请使用

SelectableText.rich(
  TextSpan(
    children: [
      TextSpan(text: "Copy me", style: TextStyle(color: Colors.red)),
      TextSpan(text: " and leave me"),
    ],
  ),
)

SelectableText 中还有一个属性列表,用于启用选项复制、粘贴、全选、剪切

        child: Center(
            child: SelectableText('Hello Flutter Developer',
                cursorColor: Colors.red,
                showCursor: true,
                toolbarOptions: ToolbarOptions(
                copy: true,
                selectAll: true,
                cut: false,
                paste: false
                ),
                style: Theme.of(context).textTheme.body2)
            ),

SelectableText 小部件

        const SelectableText(
            this.data, {
            Key key,
            this.focusNode,
            this.style,
            this.strutStyle,
            this.textAlign,
            this.textDirection,
            this.showCursor = false,
            this.autofocus = false,
            ToolbarOptions toolbarOptions,
            this.maxLines,
            this.cursorWidth = 2.0,
            this.cursorRadius,
            this.cursorColor,
            this.dragStartBehavior = DragStartBehavior.start,
            this.enableInteractiveSelection = true,
            this.onTap,
            this.scrollPhysics,
            this.textWidthBasis,
        })

我在函数内部使用 Clipboard.setData。

...
child: RaisedButton(
    onPressed: (){
        Clipboard.setData(ClipboardData(text: "$textcopy"));
},
    disabledColor: Colors.blue[400],
    child: Text("Copy", style: TextStyle(color: Colors.white),),
),

我创建了一个助手 class CopiableText 来完成我的工作。只需从下方复制 class 并将其放入您的代码中即可。

帮手class

copiable_text_widget.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class CopiableText extends StatelessWidget {
  final String text;
  final String copyMessage;
  final Widget child;

  CopiableText(this.text, {this.copyMessage, this.child});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      child: InkWell(
        onTap: () {
          Scaffold.of(context).showSnackBar(SnackBar(
            content: Text(this.copyMessage ?? 'Copied to clipboard'),
          ));
          Clipboard.setData(new ClipboardData(text: this.text));
        },
        child: Align(
          alignment: Alignment.centerLeft,
          child: Padding(
            padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 2),
            child: this.child ??
                Text(
                  this.text,
                  style: TextStyle(color: Color(0xFF1E272E), fontSize: 14),
                ),
          ),
        ),
      ),
    );
  }
}

以不同的方式使用它

import 'package:chaincargo_courier/ui/widgets/copiable_text_widget.dart';
import 'package:flutter/material.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          // Just straightforward, click to copy
          CopiableText('You are awesome'),

          // Give a custom confirmation message
          CopiableText(
            'Asia, Nepal, Biratnagar',
            copyMessage: 'Address copied to clipboard',
          ),

          // Set custom child
          CopiableText(
            'Stunning view of mount everest',
            copyMessage: 'Caption copied to clipboard',
            child: Column(
              children: [
                Image.network(
                  'https://cdn.pixabay.com/photo/2010/11/29/mount-everest-413_960_720.jpg',
                  errorBuilder: (BuildContext context, Object exception,
                      StackTrace stackTrace) {
                    return Text('Cannot load picture');
                  },
                ),
                Text('Stunning view of mount everest')
              ],
            ),
          ),
        ],
      ),
    );
  }
}

只需使用 SelectableText

 SelectableText(
                iosInfo.identifierForVendor.toString(),
              ),