Как сделать копируемый текстовый виджет во флаттере?

Когда длинная вкладка на виджете Text, появляется всплывающая подсказка с копией. При нажатии на "копировать" текстовое содержимое должно копироваться в системный буфер обмена.

Следующее будет копировать текст при длительном нажатии, но не отображать "копировать", поэтому пользователь не будет знать, содержимое копируется в буфер обмена.

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));
      },
    );
  }
}

Ответ 1

С Flutter 1.9 вы можете использовать

SelectableText("Lorem ipsum...")

При выделении текста появится контекстная кнопка "Копировать".

enter image description here

Ответ 2

Вы можете использовать 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")),
          ]),


    );
  }

EDIT

Я работал над чем-то, и я сделал следующее, поэтому я подумал о повторном рассмотрении этого ответа:

enter image description 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));
      },
    );
  }
}

Ответ 3

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"),
    ],
  ),
)

enter image description here

Ответ 4

В 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,
        })

enter image description here

Ответ 5

Выше решение не идеально подходит для iOS.

Обратите внимание на метку стрелки с помощью наконечника инструмента "Вставить", в то время как это отсутствует в подсказке "Копировать".

Что такое использование TickerProviderStateMixin?

введите описание изображения здесь