Tìm hiểu về thư viện EmojiCompat trong Android.

Xin chào tất cả các bạn, hôm nay chúng ta sẽ cùng nhau tìm hiểu về thư viện EmojiCompat trong Android.

1. EmojiCompat là gì?

Đã bao giờ bạn gặp tình trạng mà đoạn tin nhắn mà bạn nhận được có kèm các ô vuông trống hoặc các kí tự sai không ạ, ví dụ như đoạn chat dưới dây. Vấn đề trên chính và vấn đề về sự tương thích Emoji, khi mà thiết bị của bạn không có bản cập nhật các biểu tượng cảm xúc mới nhất và ai đó gửi cho bạn các biểu tượng cảm xúc đó cho bạn thì bạn sẽ nhận được các kí tự biểu tượng cảm xúc bị thiếu ở dạng ô vuông trắng. Thư viện EmojiCompat được sinh ra để giải quyết vấn đề đó, nó giữ cho các thiết bị Android được cập nhật với các biểu tượng cảm xúc mới nhất mà không cần phải thông qua các bản cập nhật Android vốn dĩ rất cồng kềnh và việc phát hành rất chậm chạp.

2. EmojiCompat hoạt động như thế nào?

Thư viện hỗ trợ EmojiCompat cung cấp các lớp để hỗ trợ các biểu tượng cảm xúc tương thích ngược với các thiết bị Android 4.4 trở lên (Api 19 và cao hơn).Bạn cũng có thể cấu hình Emoji Compat với các gói phông chữ mà bạn có thể tải xuống từ bên ngoài. EmojiCompat sẽ xác định một biểu tượng cảm xúc tương ứng với một đoạn kí tự nhất định, thay thế các kí tự đó bằng EmojiSpan và cuối cùng hiển thị chúng thành các biểu tượng cảm xúc. Bạn có thể hình dung cách mà EmojiCompat hoạt động thông qua hình sau.

3. Cài đặt

3.1. Thêm thư viện hỗ trợ vào project.

Để sử dụng thư viện hỗ trợ EmojiCompat, bạn phải thêm dường dẫn của thư viện hỗ trợ vào file bulid.gradle trong module app của bạn.

dependencies {
    ...
    compile "com.android.support:support-emoji:28.0.0"
}

Nếu bạn đang sử dụng AndroidX có thể sử dụng công cụ Refactor -> Migrate To AndroidX của Android Studio, nó sẽ tự động chuyển sang gói tương ứng bên AndroidX cho bạn.

3.2. Khởi tạo cấu hình phông chữ.

Bạn cần khởi tạo EmojiCompat để tải meta data và kiểu chữ. Vì việc khởi tạo có thể mất một chút thời gian, quá trình khởi tạo được chạy trên một luồng ở nền. Để khởi tọa các bạn làm theo các bước sau:

  • Tạo một instance của FontRequest.
  • Tạo một instance của FontRequestEmojiCompatConfig bằng ContextFontRequest.
  • Khởi tạo EmojiCompat bằng cách gọi phương thức init() và truyển vào instance của FontRequestEmojiCompatConfig Các bạn có thể tham khảo trong đoạn mã Kotlin dưới đây:
    private void initEmojiCompat() {
        final EmojiCompat.Config config;
        if (USE_BUNDLED_EMOJI) {
            config = new BundledEmojiCompatConfig(getApplicationContext());
        } else {
            final FontRequest fontRequest = new FontRequest(
                    "com.google.android.gms.fonts",
                    "com.google.android.gms",
                    "Noto Color Emoji Compat",
                    R.array.com_google_android_gms_fonts_certs);
            config = new FontRequestEmojiCompatConfig(getApplicationContext(), fontRequest);
        }
        config.setReplaceAll(true)
                .registerInitCallback(new EmojiCompat.InitCallback() {
                    @Override
                    public void onInitialized() {
                        Log.i(TAG, "EmojiCompat initialized");
                    }

                    @Override
                    public void onFailed(@Nullable Throwable throwable) {
                        Log.e(TAG, "EmojiCompat initialization failed", throwable);
                    }
                });

        EmojiCompat.init(config);
    }
  • Sau khi đã khởi tạo được EmojiCompat các bạn sử dụng EmojiCompat ở trong file giao diện xml.
<android.support.text.emoji.widget.EmojiTextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiEditText
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Bạn cũng có thể sử dụng EmojiCompat với AppCompat Widget bằng cách:

  • Implement thư viện EmojiCompat giành cho AppCompat.
dependencies {
      compile "com.android.support:support-emoji-appcompat:$version"
}
  • Implement các widget trong file layout của bạn.
<android.support.text.emoji.widget.EmojiAppCompatTextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiAppCompatEditText
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

<android.support.text.emoji.widget.EmojiAppCompatButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

4. Các thành phần trong thư viện.

Như các bạn đã thấy ở trên chúng ta có EmojiTextView, EmojiEditText và EmojiButton. Các widget này có được bằng cách sử dụng EmojiCompat với các widget TextView, EditText và Button. Các thành phần trong thư viện EmojiCompat:

  • EmojiCompat : Là thành phần chính của thư viện, nó thực hiện các tác vụ bên ngoài mà tương tác với các thành phần khác bên trong hệ thống.
  • EmojiCompat.Config: Định nghĩa cấu hình của instance khi được khởi tạo.
  • EmojiSpan: Là một lớp con có tác dụng thay thế các ký tự và render Glyph.
  • EmojiCompat Font: EmojiCompat sử dụng phông chữ để hiển thị các biểu tượng cảm xúc. Phông chữ này là phiên bản sửa đổi của phông chữ trên Android Emoji. Để cung cấp khả năng tương thích ngược để hiển thị các biểu tượng cảm xúc, tất cả các ký tự biểu tượng cảm xúc được thể hiện bằng một mã Unicode duy nhất bắt đầu bằng U + F0001. Dữ liệu của các biểu tượng cảm xúc bổ sung sẽ được chèn theo định dạng nhị phân vào phông chữ và được phân tích khi khởi chạy bởi EmojiCompat. Dữ liệu này được lư trữ trong bảng phông chữ với tag là Emji.

5. Các tùy chọn khi cấu hình.

Các bạn có thể khởi tạo một instance của EmojiCompat để tùy chỉnh. Các phương thức thông dụng để custom bao gồm:

  • setReplaceAll(): Xác định xem có nên thay đổi toàn bộ các emoji bằng EmojiSpan hay không.
  • setEmojiSpanIndicatorEnabled(): Cho biết liệu EmojiCompat có thay thế biểu tượng cảm xúc bằng EmojiSpan hay không. Khi giá trị này là true, EmojiCompat sẽ vẽ background cho EmojiSpan.
  • setEmojiSpanIndicatorColor(): Set màu cho EmojiSpan, màu mặc định sẽ là màu xanh lá cây.
  • registerInitCallback: Đăng kí nhận thông báo về trạng thái khởi tạo của EmojiCompat. Ví dụ:
private static class InitCallback extends EmojiCompat.InitCallback {
        @Override
        public void onInitialized() {
            //Todo
        }
    }

Các bạn có thể tham khảo các phương thức trong đoạn mã code Kotlin dưới đây:

val config = FontRequestEmojiCompatConfig(...)
        .setReplaceAll(true)
        .setEmojiSpanIndicatorEnabled(true)
        .setEmojiSpanIndicatorColor(Color.GREEN)
        .registerInitCallback(object: EmojiCompat.InitCallback() {
            ...
        })

6. Sử dụng EmojiCompat với customs widget.

Bạn luôn luôn có thể sử dụng phương thức process () để xử lý các CharSequence trong ứng dụng của bạn và thêm nó vào bất kỳ widget nào có thể hiển thị các Span ví dụ như TextView.

public class CustomTextView extends AppCompatTextView {

    private EmojiTextViewHelper mEmojiTextViewHelper;

    public CustomTextView(Context context) {
        this(context, null);
    }

    public CustomTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        getEmojiTextViewHelper().updateTransformationMethod();
    }

    @Override
    public void setFilters(InputFilter[] filters) {
        super.setFilters(getEmojiTextViewHelper().getFilters(filters));
    }

    @Override
    public void setAllCaps(boolean allCaps) {
        super.setAllCaps(allCaps);
        getEmojiTextViewHelper().setAllCaps(allCaps);
    }
    
    private EmojiTextViewHelper getEmojiTextViewHelper() {
        if (mEmojiTextViewHelper == null) {
            mEmojiTextViewHelper = new EmojiTextViewHelper(this);
        }
        return mEmojiTextViewHelper;
    }

}

Sau đó set text cho custom textview:

// Custom TextView
        private static final String EMOJI = "\uD83D\uDC69\u200D\uD83C\uDFA4";
        final TextView customTextView = findViewById(R.id.emoji_custom_text_view);
        customTextView.setText(getString(R.string.custom_text_view, EMOJI));

Với EditText:

class MyEditText(context: Context) : AppCompatEditText(context) {

    private val emojiEditTextHelper: EmojiEditTextHelper by lazy(LazyThreadSafetyMode.NONE) {
        EmojiEditTextHelper(this).also {
            super.setKeyListener(it.getKeyListener(keyListener))
        }
    }

    override fun setKeyListener(input: KeyListener?) {
        input?.also {
            super.setKeyListener(emojiEditTextHelper.getKeyListener(it))
        }
    }

    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
        val inputConnection: InputConnection = super.onCreateInputConnection(outAttrs)
        return emojiEditTextHelper.onCreateInputConnection(
                inputConnection,
                outAttrs
        ) as InputConnection
    }
}

7. Tổng kết.

Cảm ơn các bạn đã theo dõi bài viết. Các bạn cũng có thể tham khảo nguồn tại trang https://developer.android.com/guide