表情符号(表情)视图/键盘布局的实现

Posted

技术标签:

【中文标题】表情符号(表情)视图/键盘布局的实现【英文标题】:Implementations of Emoji (Emoticon) View/Keyboard Layouts 【发布时间】:2013-05-27 08:12:58 【问题描述】:

我试图弄清楚表情符号(表情)选择是如何在 Facebook 应用和 Google Hangouts 应用上实现的。我查看了 android API 示例中的 SoftKeyboard 演示应用程序,但这些表情符号视图的显示看起来不像 SoftKeyboard。它的外观和行为更像是自定义 Dialog 视图。有谁知道这些是如何实现的?

Facebook 应用程序

Google 环聊应用

另外,Unicode 是发送表情符号的最佳方式还是有其他选择?我注意到像\u1F601 这样的一些Unicode 序列不会呈现相应的表情符号,而是该序列只显示为1

EditText messageInput = (EditText) findViewById(R.id.message_input);
messageInput.getText().append("\u1F601");

【问题讨论】:

键盘不需要看起来像软键盘——键盘可以创建它想要的任何自定义视图,而且几乎只有玩游戏的人才会真正使用 KeyboardView 类——任何投入大量时间的人他们的键盘最终会生成自定义视图。 相关:***.com/questions/3341702/… 【参考方案1】:

我发现了一个非常有用的Emoticon Keyboard。此键盘不使用 Unicode 序列,而只是使用本地图像资源。我认为这种类型的键盘只能在这个应用程序中使用,而不能在其他应用程序或操作系统中使用。

因此,我将包含资产的 ImageView 替换为包含 Unicode 序列的 TextView

在交叉引用Supported Unicode Sequences 和Visual Unicode Database 之后,我意识到\u1F601 是32 位Unicode 表示,16 位表示可以设置为:

EditText messageInput = (EditText) findViewById(R.id.message_input);
messageInput.getText().append("\ud83d\ude01");

【讨论】:

如何将 32 位表示转换为 16 位。有什么模式可以做到这一点。【参考方案2】:

你可以使用这个基于 Hieu Rocker 库的库: https://github.com/ankushsachdeva/emojicon

这就是它的样子

【讨论】:

这是表情符号的最佳库:D 你有和 gradle 集成相同的库 这真是太棒了!请在Android Studio的项目中找到here如何实现【参考方案3】:

如果您不想详细了解如何实现 Emoji-Keyboard 功能,可以尝试以下库:

Rockerhieu / emojicon: 使用片段实现表情符号键盘(您需要使用 DialogFragment 处理它的显示。它不支持更改布局和默认是 Hole Dark 主题;

Android Emoji Keyboard: 基于 Rockerhieu 的工作,我构建了另一个库,它提供的表情符号键盘更接近我们在 WhatsApp 或 Telegram 等应用程序中看到的内容。您可以将布局作为 LinearLayout 处理,因此,您可以自己处理与软键盘的交互(如下所述),或者选择使用库提供的 Telegram Panel 或 WhatsApp Panel 来为您完成。

PS1:两个库都是 Apache 许可证

第 01 部分:构建布局

为您想要在键盘中使用的每个 Emoji-Page 创建一个 GridView。例如:

在 Fragments 中绑定创建的视图:

public class FragmentEmojiNature extends FragmentEmoji 

public static final String TAG = "FragmentEmojiNature";

private View mRootView;
private Emoji[] mData;
private boolean mUseSystemDefault = false;

private static final String USE_SYSTEM_DEFAULT_KEY = "useSystemDefaults";
private static final String EMOJI_KEY = "emojic";

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    this.mRootView = inflater.inflate(R.layout.frag_emoji_nature, container, false);
    return this.mRootView;


@Override
public void onViewCreated(View view, Bundle savedInstanceState) 
    GridView gridView = (GridView) view.findViewById(R.id.Emoji_GridView);
    Bundle bundle = getArguments();
    if (bundle == null) 
        mData = Nature.DATA;
        mUseSystemDefault = false;
     else 
        Parcelable[] parcels = bundle.getParcelableArray(EMOJI_KEY);
        mData = new Emoji[parcels.length];
        for (int i = 0; i < parcels.length; i++) 
            mData[i] = (Emoji) parcels[i];
        
        mUseSystemDefault = bundle.getBoolean(USE_SYSTEM_DEFAULT_KEY);
    
    gridView.setAdapter(new EmojiAdapter(view.getContext(), mData, mUseSystemDefault));
    gridView.setOnItemClickListener(this);

创建一个包含视图分页器和一些组件来控制视图分页器转换的新布局(在我的例子中,我使用了一个名为SmartTabLayout 的第三方库,如下所示:

<com.ogaclejapan.smarttablayout.SmartTabLayout
    android:id="@+id/emoji_tabs"
    android:layout_
    android:layout_
    android:layout_weight="1"
    app:stl_clickable="true"
    app:stl_defaultTabBackground="@color/rsc_emoji_tab_bkg"
    app:stl_defaultTabTextAllCaps="true"
    app:stl_defaultTabTextColor="#000"
    app:stl_defaultTabTextHorizontalPadding="0dip"
    app:stl_defaultTabTextMinWidth="0dp"
    app:stl_defaultTabTextSize="14sp"
    app:stl_distributeEvenly="true"
    app:stl_dividerColor="@color/rsc_emoji_tab_bkg"
    app:stl_drawDecorationAfterTab="true"
    app:stl_indicatorColor="@color/rsc_emoji_tab_indicator"
    app:stl_indicatorGravity="bottom"
    app:stl_indicatorInFront="false"
    app:stl_indicatorInterpolation="smart"
    app:stl_indicatorThickness="2dp"
    app:stl_overlineThickness="0dp"
    app:stl_titleOffset="24dp"
    app:stl_underlineThickness="0dp"/>

<ImageButton
    android:id="@+id/backspace"
    android:layout_
    android:layout_
    android:background="@color/rsc_emoji_tab_bkg"
    android:paddingLeft="10dip"
    android:paddingRight="10dip"
    android:src="@drawable/sym_keyboard_delete_holo_dark"/>

PS2:上面的按钮是为了提供退格功能

第 02 部分:控制器层

创建一个适配器来控制 GridView 中表情符号的插入,例如:

public class EmojiAdapter extends ArrayAdapter<Emoji> 

    private boolean mUseSystemDefault = Boolean.FALSE;

    // CONSTRUCTOR
    public EmojiAdapter(Context context, Emoji[] data) 
        super(context, R.layout.rsc_emoji_item, data);
    

    public EmojiAdapter(Context context, List<Emoji> data) 
        super(context, R.layout.rsc_emoji_item, data);
    

    public EmojiAdapter(Context context, List<Emoji> data, boolean useSystemDefault) 
        super(context, R.layout.rsc_emoji_item, data);
        this.mUseSystemDefault = useSystemDefault;
    

    public EmojiAdapter(Context context, Emoji[] data, boolean useSystemDefault) 
        super(context, R.layout.rsc_emoji_item, data);
        this.mUseSystemDefault = useSystemDefault;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        View view = convertView;

        if (view == null) 
            view = View.inflate(getContext(), R.layout.rsc_emoji_item, null);
            view.setTag(new ViewHolder(view, this.mUseSystemDefault));
        

        Emoji emoji = this.getItem(position);
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.icon.setText(emoji.getEmoji());

        return view;
    

    static class ViewHolder 
        EmojiTextView icon;

        public ViewHolder(View view, Boolean useSystemDefault) 
            this.icon = (EmojiTextView) view.findViewById(R.id.emoji_icon);
            this.icon.setUseSystemDefault(useSystemDefault);
        
    

创建将膨胀每个表情符号页面的类,将表情符号(遵循 Unicode 模式)传递到 GridView。即:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) 
    GridView gridView = (GridView) view.findViewById(R.id.Emoji_GridView);
    Bundle bundle = getArguments();
    if (bundle == null) 
        mData = Nature.DATA;
        mUseSystemDefault = false;
     else 
        Parcelable[] parcels = bundle.getParcelableArray(EMOJI_KEY);
        mData = new Emoji[parcels.length];
        for (int i = 0; i < parcels.length; i++) 
            mData[i] = (Emoji) parcels[i];
        
        mUseSystemDefault = bundle.getBoolean(USE_SYSTEM_DEFAULT_KEY);
    
    gridView.setAdapter(new EmojiAdapter(view.getContext(), mData, mUseSystemDefault));
    gridView.setOnItemClickListener(this);

创建两个类:一个从 EditText 扩展,另一个从 TextView 扩展。拦截其中每一个的输入来识别输入的元素何时是 Emoji,如果是,则添加一个 spannable 以便显示图标(如果要覆盖系统默认的 emojis 主要需要例如,有一些看起来像 whats-app 或电报的东西);

处理与软键盘的交互。可以通过两种方式完成:

    在软键盘上绘制一个对话框; 禁用软键盘与activity的交互,自行处理屏幕绘制;

PS3:我很难尝试格式化代码,但仍有一些 XML 没有显示,如果有人可以修复它,我将不胜感激

【讨论】:

仅仅链接到您自己的库(或实用程序)并不是一个好的答案。链接到它,解释它解决问题的原因,提供使用它的代码并拒绝提供更好的答案。见:How can I link to an external resource in a community-friendly way? 你是如何创建 gif 的? 致此答案的作者:请添加第二个库(Android 表情符号键盘)的链接。 如果您想要表情符号库而不需要导入和编译整个项目,只需在您的build.gradle 中包含以下条目:compile 'br.com.instachat:emoji-library:1.0.6@aar'【参考方案4】:

视图组可见或消失也可以理解,它不需要对话框。 每次初始化情感时,我总是使用像 [happy]=R.drawable.happy 这样的键值。 这是情感的文本,而像[快乐]这样的内容

public SpannableString textToImage(String content,Context c)
    SpannableString ss = new SpannableString(content);
    int starts = 0;
    int end = 0;
    if(content.indexOf("[", starts) != -1 && content.indexOf("]", end) != -1)
        starts = content.indexOf("[", starts);
        end = content.indexOf("]", end);
         SharedPreferences shared=c.getSharedPreferences("emotion",0);
         int resource=shared.getInt(content,0);
        try 
            Drawable drawable =c.getResources().getDrawable(resource);  
            if (drawable != null) 
                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 
                ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);  
                ss.setSpan(span, starts,end + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
            
         catch (Exception ex)

        
    
    return ss;


【讨论】:

【参考方案5】:

您可以将此库用于 Android:https://github.com/rockerhieu/emojicon

【讨论】:

【参考方案6】:

案例 1:首先推出的自定义键盘 Keypad 是根据 Android Keypad 的大小创建的,因为这个 Keypad 是 Height is Unknown 最初,自定义键盘是使用固定高度创建的 - 在这种情况下,您必须将编辑区域移动到具有固定高度的自定义键盘上方(可以通过在放置编辑区域的父布局上设置填充来使用( parentLayout-> setPadding ( 0 , 0 , 0 ,Height) ->其中 height 是您的初始键盘高度)。 注意:当自定义键盘被销毁或隐藏时,不要忘记将填充设置为 0。

案例 2:Android 文本键盘首先启动

当自定义键盘启动时,键盘是已知的写入首选项使用此高度。 无需设置任何填充,因为这是 Android 键盘为您做的。

【讨论】:

以上是关于表情符号(表情)视图/键盘布局的实现的主要内容,如果未能解决你的问题,请参考以下文章

android studio 从默认键盘打开表情符号键盘

如何使用 swiftui 创建表情符号键盘?

如何禁用 iOS 8 表情符号键盘?

在iOS 9.0中以编程方式显示表情符号键盘

未使用表情符号键盘调用 UIKeyboardWillChangeFrame 通知

UICollectionView 中的高内存使用 [重复]