Implementations of Emoji (Emoticon) View/Keyboard Layouts Implementations of Emoji (Emoticon) View/Keyboard Layouts android android

Implementations of Emoji (Emoticon) View/Keyboard Layouts


I found a very useful Emoticon Keyboard. This keyboard is not using Unicode sequences but rather just local image assets. I am thinking that this type of keyboard can only be useful within this app and not with other apps or Operating Systems.

So instead I am replacing the ImageView containing an asset with a TextView containing a Unicode sequence.

After cross referencing Supported Unicode Sequences as well as the Visual Unicode Database I realized that \u1F601 was a 32 bit Unicode representation, and the 16bit representation can be set like :

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


You can use this library based on Hieu Rocker's library:https://github.com/ankushsachdeva/emojicon

This is how it looks

Screenshot


If you don't want to get into details of how to implement the Emoji-Keyboard functionality, you can try these libraries:

  • Rockerhieu / emojicon: implements the Emoji-Keyboard using fragments (you will need to handle the display of it using a DialogFragment. It doesn't have support for changing the layout and the default one is Hole Dark theme;

  • Android Emoji Keyboard: Based on Rockerhieu work I've built another lib that provides the emoji-keyboard as closer to what we've seen in apps such as WhatsApp or Telegram. You can handle the layout as a LinearLayout and, therefore, handle the interaction with the soft keyboard yourself (as described below) or choose to use Telegram Panel or WhatsApp Panel, both provided by the library, that does it for you.

PS1: Both libraries are Apache License

Final Result should look like that

Part 01: Building the layout

  • Create a GridView for each Emoji-Page you want in your keyboard. For instance:

  • Bind the created views in 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";@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {    this.mRootView = inflater.inflate(R.layout.frag_emoji_nature, container, false);    return this.mRootView;}@Overridepublic 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);}

    }

  • Create a new layout containing a view pager and some component to control the view pager transition (in my case I've used a third part library called SmartTabLayout as shown below:

    <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: the button above exists in order to provide the backspace functionality

Part 02: Controller layer

  • Create an adapter to control the insertion of the emojis in the GridView, for example:

    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);        }    }}
  • Create classes that will inflate each one of the emoji-pages passing the emojis (following the Unicode pattern) to the GridView. i.e.:

    @Overridepublic 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);}
  • Create two classes: one that extends from EditText and another that extends from TextView. Intercept the input of each one of them to identify when the typed element is an Emoji, if so, add a spannable in order to display the icon (mainly need if you want to override the system default emojis to have something that looks like whats-app or telegram, for instance);

  • Handle the interaction with soft-keyboard. It can be done in two ways:

    1. Draw a Dialog over the soft keyboard;
    2. Disable the interaction of the soft keyboard with the activity and handle the screen draw yourself;

PS3: I had a hard time trying to format the code and still some of the XML is not shown, if someone can fix it I would be thankfull