搜索插件、代码仓与 APP 分类

emoji_keyboard_flutter 封面
插件详情v1.7.5

emoji_keyboard_flutter

一个 Flutter 包,提供只能输入表情符号的键盘!

AndroidiOS
近 30 天下载
240
喜欢数
32
Pub 分数
140

安装插件

flutter pub add emoji_keyboard_flutter

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

一个 Flutter 包,专为输入表情符号而设计的键盘。它用自定义界面取代了标准输入法,用户只能选择和输入表情符号,非常适合用于轻松或富有表现力的交流。该键盘设计轻量,可无缝集成到 Android 和 iOS 的 Flutter 应用中。在需要仅使用表情符号互动以提升用户体验的场景下特别有用,例如社交应用或创意消息平台。

适合场景

  • 仅表情符号的即时通讯应用
  • 有趣的用户界面
  • 创意内容创作工具
  • 社交媒体集成
  • 交互式聊天功能

主要特点

  • 专用表情符号输入
  • 跨平台支持(Android 和 iOS)
  • 轻量且易于集成
  • 可自定义的表情符号网格
  • 无缝 Flutter 集成

适合对象

  • 开发有趣或富有表现力的应用程序的开发者
  • 面向年轻受众的应用
  • 消息或社交平台
  • 以表情符号为中心的UI实验

使用建议

  • 不适用于传统文本输入
  • 仅限表情符号工作流
  • 可能需要为用户提供额外的用户体验指导
  • 取决于平台键盘处理行为

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

Flutter Emoji Keyboard

pub package

A Flutter package that provides a keyboard where you can only type with emojis!

It's a keyboard the way you expect it and more! But with less letters and only emojis.

Emoji selection Skin selection Search option
Emoji selection Skin selection Search option
Emoji popup widget Recent emojis Dark or Light mode
Emoji selection Skin selection Search option

Key features

Smooth and intuitive keyboard layout with all the emojis up to unicode 16.0 available in separate 8 categories with a 'recent chosen' tab.

You can easily switch between categories by swiping or selecting the category from the top bar.

Emojis that cannot be displayed are filtered out (only for Android)

You can even search for your emoji by using the search functionality available in the bottom bar.

From this keyboard you can also delete an emoji from the position of the cursor or add a space from the bottom bar.

Determine the height of the keyboard and show or hide it using a simple variable

The emojis have an indicator which shows if you can add a skin component to them. If this is the case you can add one by long pressing the emoji and selecting a skin component from the resulting popup window.

Change the default light setting to dark mode

Instead of the keyboard you can also use the quick emoji popup widget. Select one of the many quick reaction emojis or from your recent emojis. The widget has a "+" button that you can implement to open the regular emoji keyboard.

Usage

To use this plugin, add emoji_keyboard_flutter as dependency in your pubspec.yaml file.

Full Sample Usage

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Emoji Keyboard',
      home: MyHomePage(key: UniqueKey(), title: 'Emoji Keyboard'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({required Key key, required this.title}) : super(key: key);
  final String title;

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  bool showEmojiKeyboard = false;
  final TextEditingController controller = TextEditingController();
  int emojiReactionIndex = -1;
  bool showEmojiPopup = false;
  Offset emojiPopupPosition = Offset.zero;
  List<String> emojiReactions = ['', ''];
  bool darkMode = false;

  void backButtonFunctionality() {
    if (emojiReactionIndex != -1) {
      emojiReactionIndex = -1;
    }
    if (showEmojiPopup) {
      setState(() {
        showEmojiPopup = false;
      });
      return;
    }
    if (showEmojiKeyboard) {
      setState(() {
        showEmojiKeyboard = false;
      });
      return;
    }
    if (Platform.isAndroid) {
      SystemNavigator.pop();
    } else {
      exit(0);
    }
  }

  void onTapEmojiField() {
    emojiReactionIndex = -1;
    if (showEmojiPopup) {
      setState(() {
        showEmojiPopup = false;
      });
    }
    if (!showEmojiKeyboard) {
      setState(() {
        showEmojiKeyboard = true;
      });
    }
  }

  void onLongPressMessage(
      BuildContext context, LongPressStartDetails details, int messageIndex) {
    emojiReactionIndex = messageIndex;
    setState(() {
      showEmojiPopup = true;
      emojiPopupPosition = details.globalPosition;
    });
  }

  void handleEmojiPopupAction(EmojiPopupAction action) {
    showEmojiPopup = false;
    if (action is OutsideClicked) {
      emojiReactionIndex = -1;
    } else if (action is ButtonPressed) {
      showEmojiKeyboard = true;
    } else if (action is EmojiSelected) {
      final String newEmoji = action.emoji;
      if (emojiReactions[emojiReactionIndex] == newEmoji) {
        emojiReactions[emojiReactionIndex] = '';
      } else {
        emojiReactions[emojiReactionIndex] = action.emoji;
      }
      emojiReactionIndex = -1;
    }
    setState(() {});
  }

  void onActionEmojiChanged(String emoji) {
    if (emojiReactionIndex != -1) {
      emojiReactions[emojiReactionIndex] = emoji;
      emojiReactionIndex = -1;
      if (showEmojiKeyboard) {
        showEmojiKeyboard = false;
      }
      setState(() {});
    }
  }

  TextEditingController? getEmojiController() {
    if (emojiReactionIndex != -1) {
      return null;
    } else {
      return controller;
    }
  }

  Widget messageWidget(int messageIndex, String messageText) {
    return GestureDetector(
      onLongPressStart: (details) =>
          onLongPressMessage(context, details, messageIndex),
      child: Stack(
        children: [
          Container(
            width: MediaQuery.of(context).size.width,
            color: emojiReactionIndex == messageIndex
                ? Colors.cyan[200]
                : Colors.transparent,
            child: Container(
              margin: const EdgeInsets.all(8.0),
              padding: const EdgeInsets.all(12.0),
              decoration: BoxDecoration(
                color: messageIndex == 0 ? Colors.green[200] : Colors.blue[200],
                borderRadius: BorderRadius.only(
                  topLeft: messageIndex == 0
                      ? const Radius.circular(30.0)
                      : Radius.zero,
                  topRight: messageIndex == 1
                      ? const Radius.circular(30.0)
                      : Radius.zero,
                  bottomLeft: const Radius.circular(30.0),
                  bottomRight: const Radius.circular(30.0),
                ),
              ),
              child: Text(
                messageText,
                style: const TextStyle(fontSize: 16.0),
              ),
            ),
          ),
          if (emojiReactions[messageIndex] != '')
            Positioned(
              bottom: 0,
              right: 50,
              child: Container(
                padding: const EdgeInsets.all(4.0),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(12.0),
                ),
                child: Text(
                  emojiReactions[messageIndex],
                  style: const TextStyle(fontSize: 16.0),
                ),
              ),
            ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (bool didPop, result) {
        if (!didPop) {
          backButtonFunctionality();
        }
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Stack(
          children: [
            Column(
              children: [
                Expanded(
                  child: ListView(
                    reverse: true,
                    children: [
                      Container(
                        alignment: Alignment.topCenter,
                        padding: const EdgeInsets.only(
                            bottom: 12.0, left: 8, right: 8, top: 12),
                        child: TextFormField(
                          onTap: onTapEmojiField,
                          controller: controller,
                          decoration: const InputDecoration(
                              border: OutlineInputBorder()),
                          readOnly: true,
                          showCursor: true,
                        ),
                      ),
                      messageWidget(1,
                          'Or press the Textfield below to start typing with the emoji keyboard!'),
                      messageWidget(0,
                          'This is an example message. Long press to do an emoji reaction on this message!'),
                    ],
                  ),
                ),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: EmojiKeyboard(
                    emojiController:
                        emojiReactionIndex == -1 ? controller : null,
                    onEmojiChanged: onActionEmojiChanged,
                    showEmojiKeyboard: showEmojiKeyboard,
                    emojiKeyboardHeight: 440, // optional defaults to 350
                    darkMode: darkMode, // optional defaults to false
                    emojiKeyboardAnimationDuration: const Duration(
                        milliseconds: 400), // optional defaults to null
                  ),
                ),
              ],
            ),
            EmojiKeyboardPopup(
              position: emojiPopupPosition,
              onAction: handleEmojiPopupAction,
              showEmojiPopup: showEmojiPopup,
              darkMode: darkMode, // optional defaults to false
              popupWidth: 350, // optional defaults to 350
              highlightedEmoji: emojiReactionIndex == -1
                  ? null
                  : emojiReactions[
                      emojiReactionIndex], // optional defaults to null
              emojiPopupAnimationDuration: const Duration(
                  milliseconds: 400), // optional defaults to null
            ),
          ],
        ),
      ),
    );
  }
}

See the example directory for the complete sample app.

所属分类

依赖

依赖清单 3 项

源码仓库

使用此插件的项目

暂无相关数据。