letsintegreat
letsintegreat

Reputation: 3366

How to accept images in TextField Flutter

In android, when we take a screenshot, it gets stored in the clipboard. Now if I open WhatsApp, and tap on the message field. My keyboard gives me a suggestion to paste the image from the clipboard, as shown below.

enter image description here

I am guessing this is because the TextField somehow tells the OS that it can accept images. How can I achieve the same behavior in a TextField of flutter? If not a TextField, is there any way to implement a button that can paste image from clipboard into our app?

I have found a pub package for other platforms - https://pub.dev/packages/pasteboard but it doesn't seem to support android.

Upvotes: 8

Views: 2358

Answers (4)

L's World
L's World

Reputation: 465

Actually you do not need to paste the image into the TextField, you can wrap the Image area and TextField into a Container/Column which looks like a TextField, make sure to change background of everything to match TextField background.

Column(Children: [ImageArea(), TextField()])

Then enable the paste action in context menu and for ctrl+v action.

To make paste always show in context menu (by default it only shows when you have text in clipboard, not images):

TextField(contextMenuBuilder: (BuildContext context, EditableTextState state) {
    final List<ContextMenuButtonItem> buttonItems =
        state.contextMenuButtonItems;

    final pasteButton = buttonItems
        .firstWhereOrNull((x) => x.type == ContextMenuButtonType.paste);

    if (pasteButton == null) {
      buttonItems.add(ContextMenuButtonItem(
        onPressed: () {
          // read clipboard using pasteboard or super_clipboard etc.
        },
        type: ContextMenuButtonType.paste,
      ));
    }

    return AdaptiveTextSelectionToolbar.buttonItems(
      anchors: state.contextMenuAnchors,
      buttonItems: buttonItems,
    );
  })

To make ctrl + v work:

TextField(focusNode: FocusNode(
onKeyEvent: (node, event) {
  // Check if 'V' key is pressed
  bool isVKeyPressed = (event.physicalKey == PhysicalKeyboardKey.keyV);

  // Check if 'Ctrl' or 'Meta' key is pressed
  bool isCtrlOrMetaPressed =
      HardwareKeyboard.instance.physicalKeysPressed.any(
    (key) =>
        key == PhysicalKeyboardKey.controlLeft ||
        key == PhysicalKeyboardKey.controlRight ||
        key == PhysicalKeyboardKey.metaLeft ||
        key == PhysicalKeyboardKey.metaRight,
  );

  // Only trigger paste action if both 'V' and 'Ctrl/Meta' keys are pressed
  if (isVKeyPressed && isCtrlOrMetaPressed) {
    handlePaste();
  }
},

);)

Upvotes: 0

HannesH
HannesH

Reputation: 986

very good question, on the bleeding edge of flutter

to get this functionality switch to the flutter master channel (command flutter channel master), this will now include PR 110052 which adds this functionality.

to use it simply add this to your TextField:

//...
  contentInsertionConfiguration: ContentInsertionConfiguration(
    onContentInserted : (_){/*your cb here*/}
    allowedMimeTypes: ["image/png",/*...*/],
  }),
//...

this will then use the android specific content commit api to (as you guessed) tell the OS that your TextField accepts the given mimetypes; gboard will recognize this and suggest the content with fitting mimetypes in your clipboard

Upvotes: 3

Tamer El Zein
Tamer El Zein

Reputation: 1

In Flutter, you can use the FlutterClipboard package to interact with the system clipboard.

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

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text("My Widget"),
      ),
      body: Column(
        children: [
          TextField(
            decoration: InputDecoration(
              hintText: "Paste the screenshot here",
            ),
            keyboardType: TextInputType.multiline,
            maxLines: null,
            onTap: () async {
              var clipboardData = await Clipboard.getData(Clipboard.kTextPlain);
              if (clipboardData != null && clipboardData.text != null) {
                setState(() {
                  _textEditingController.text = clipboardData.text;
                });
              }
            },
          ),
        ],
      ),
    );
  }
}

Upvotes: 0

Iheb Briki
Iheb Briki

Reputation: 276

You can use this package it supports all platforms super_clipboard then customize the process by adding an icon button for example.

follow the installation steps because the plugin uses Rust internally to implement low-level platform-specific functionality

Upvotes: 1

Related Questions