95

When long tab on Text widget, a tooltip show up with 'copy'. When click on the 'copy' the text content should copy to system clipboard.

The following will copy the text on long tap, but does not show up 'copy', so user will not know, the content is copied to the clipboard.

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));
      },
    );
  }
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83

9 Answers9

144

Since Flutter 1.9 you can use

SelectableText("Lorem ipsum...")

When text is selected the "Copy" context button will appear.

enter image description here

Frank Treacy
  • 3,386
  • 1
  • 16
  • 16
77

You can use a SnackBar to notify the user about the copy.

Here is a relevant code:

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

I was working on something and I did the followin, so I thought of revisiting this answer:

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));
      },
    );
  }
}
Shady Aziza
  • 50,824
  • 20
  • 115
  • 113
16

There is also list of properties it in SelectableText to enable option copy, paste, selectAll, cut

        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 widget

        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

Amit Prajapati
  • 13,525
  • 8
  • 62
  • 84
  • 1
    Can you select part of text on ios? I found it can only select all on ios and can select part of text on android. – David Dec 30 '19 at 02:20
  • @David did you ever find a solution for this? I'm in a big bind because the app I created was entirely tested on Android / Linux, and now IOS doesn't allow text selection! Any help is greatly appreciated. – Seth Jul 01 '20 at 11:21
12
SelectableText(
  "Copy me",
  onTap: () {
    // you can show toast to the user, like "Copied"
  },
)

If you want to have different styling for text, use

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

enter image description here

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
7

I use Clipboard.setData inside function.

...
child: RaisedButton(
    onPressed: (){
        Clipboard.setData(ClipboardData(text: "$textcopy"));
},
    disabledColor: Colors.blue[400],
    child: Text("Copy", style: TextStyle(color: Colors.white),),
),
  • Welcome to Stack Overflow! Please don't answer just with source code. Try to provide a nice description about how your solution works. See: [How do I write a good answer](https://stackoverflow.com/help/how-to-answer)?. Thanks – Selim Yildiz Nov 21 '19 at 19:31
1

I created a helper class CopiableText to accomplish my job. Just copy the class from below and put it in your code.

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

Use it in different ways

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')
              ],
            ),
          ),
        ],
      ),
    );
  }
}
bikram
  • 7,127
  • 2
  • 51
  • 63
1

Just use SelectableText

 SelectableText(
                iosInfo.identifierForVendor.toString(),
              ),
Lam.Truong
  • 69
  • 2
  • 2
0

Support Links and Copy&Paste

If you want to support both Links and Copy&Paste, use the SelectableLinkify widget.

This widget is part of the flutter_linkify package.

SelectableLinkify(
  text: "Made by https://cretezy.com\n\nMail: example@gmail.com",
);

enter image description here

genericUser
  • 4,417
  • 1
  • 28
  • 73
0

With Flutter version Flutter 3.3, you can now use SelectionArea.

It uses a platform-specific manner (using a Material toolbar on Android, and a Cupertino toolbar on iOS)!

enter image description here

SelectionArea(
          child: Center(
            child: Column(
              children: const <Widget>[
                Text('Item 0', style: TextStyle(fontSize: 50.0)),
                Text('Item 1', style: TextStyle(fontSize: 50.0)),
              ],
            ),
          ),
        )

You can also customize the menu Toolbar using the contextMenuBuilder property.

MendelG
  • 14,885
  • 4
  • 25
  • 52