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

我正试图弄清楚如何在Facebook应用和Google Hangouts应用上实现表情符号(表情符号)选项。 我查看了Android API示例中的SoftKeyboard Demo应用程序,但是这些表情符号视图的显示看起来不像SoftKeyboard 。 它的外观和行为更像一个自定义的Dialog视图。 有没有人有这些如何实施的想法?

Facebook应用程序

Facebook的

Google环聊应用

视频群聊

而且, Unicode是发送表情符号的最佳方式还是有其他select? 我注意到像\u1F601这样的一些Unicode序列不会渲染相应的表情符号,而是这个序列显示为1

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

我发现了一个非常有用的表情符号键盘 。 此键盘不使用Unicode序列,而只使用本地图像资源。 我在想,这种types的键盘只能在这个应用程序中有用,而不能与其他应用程序或操作系统。

所以相反,我正在用包含Unicode序列的TextViewreplace包含资源的ImageView

在交叉引用支持的Unicode序列以及Visual Unicode数据库之后,我意识到\u1F601是一个32位的Unicode表示,而16位表示可以像下面这样设置:

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

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

这是它的样子

截图

视图组可见或不见也可以重新定义,它不需要对话框。 每次初始化情绪,我总是使用一个关键值,如[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; } 

如果您不想详细了解如何实现表情符号键盘function,则可以尝试下列这些库:

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

  • Android Emoji键盘 :基于Rockerhieu的工作,我已经构build了另一个提供表情符号键盘的接近于WhatsApp或Telegram等应用程序的库。 您可以将布局作为LinearLayout进行处理,因此可以自己处理与软键盘的交互(如下所述),也可以select使用由库提供​​的Telegram Panel或WhatsApp Panel来实现。

PS1:这两个库都是Apache许可证

最终结果应该是这样的

第1部分:构build布局

  • 为您的键盘上的每个Emoji-Page创build一个GridView。 例如:

  • 将创build的视图绑定到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); } 

    }

  • 创build一个新的布局,其中包含一个视图页面和一些组件来控制视图页面转换(在我的例子中,我使用了第三部分库叫SmartTabLayout ,如下所示:

     <com.ogaclejapan.smarttablayout.SmartTabLayout android:id="@+id/emoji_tabs" android:layout_width="0dip" android:layout_height="40dip" 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_width="wrap_content" android:layout_height="match_parent" android:background="@color/rsc_emoji_tab_bkg" android:paddingLeft="10dip" android:paddingRight="10dip" android:src="@drawable/sym_keyboard_delete_holo_dark"/> 

PS2:上面的button是为了提供退格function而存在的

第02部分:控制器层

  • 创build一个适配器来控制在GridView中插入emojis,例如:

     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); } } } 
  • 创build一些类,将每个将表情符号页传递给emojis(在unicode模式之后)的网格视图中。 即:

     @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); } 
  • 创build两个类:一个从EditText扩展,另一个从TextView扩展。 截取其中每一个的input,以确定何时该types的元素是表情符号,如果是这样,添加一个spannable为了显示图标(主要是需要,如果你想重写系统默认表情符号有东西看起来像什么 – 例如app或legram);

  • 用软键盘处理交互。 它可以通过两种方式完成:

    1. 在软键盘上画一个对话框;
    2. 禁用软键盘与活动的交互,并处理自己的画面;

PS3:我很难尝试格式化代码,但仍然有一些XML没有显示,如果有人能修复它,我会感谢

你可以使用Android的这个库: https : //github.com/rockerhieu/emojicon

情况1:首先启动自定义小键盘基于Android小键盘的大小创build小键盘,因为此小键盘的高度是未知的最初,定制小键盘是用固定高度创build的 – 在这种情况下,您必须将编辑区域移动到具有固定高度的自定义键盘(可以通过在放置编辑区域的父布局上设置填充(parentLayout-> setPadding(0,0,0,Height) – >其中height是您的初始键盘高度)注意: Donot忘记当自定义键盘被销毁或隐藏时,将填充设置为0。

案例2:首先推出Android文本键盘

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