Khả năng tương thích với biểu tượng cảm xúc

Thư viện hỗ trợ EmojiCompat được dùng để cập nhật biểu tượng cảm xúc mới nhất trên các thiết bị Android. Thư viện này ngăn ứng dụng hiển thị các ký tự biểu tượng cảm xúc bị thiếu dưới dạng ☐, đồng thời cho bạn biết thiết bị không có phông chữ để hiển thị văn bản đó. Khi sử dụng thư viện hỗ trợ EmojiCompat, người dùng ứng dụng không cần phải đợi bản cập nhật của hệ điều hành Android để có thể sử dụng biểu tượng cảm xúc mới nhất.

Biểu tượng cảm xúc trên thiết bị
Hình 1. So sánh biểu tượng cảm xúc

Hãy tham khảo các tài nguyên liên quan sau:

  • Khả năng tương thích với biểu tượng cảm xúc trên ứng dụng mẫu. Xem bằng Java | Kotlin

Cách thức hoạt động của EmojiCompat

Thư viện hỗ trợ EmojiCompat cung cấp các lớp triển khai hỗ trợ biểu tượng cảm xúc tương thích ngược trên các thiết bị chạy Android 4.4 (API cấp 19) trở lên. Bạn có thể định cấu hình EmojiCompat với các phông chữ theo gói hoặc có thể tải xuống. Để biết thêm thông tin về cách định cấu hình, hãy tham khảo các phần sau:

EmojiCompat xác định biểu tượng cảm xúc cho một CharSequence cụ thể, thay thế biểu tượng cảm xúc bằng EmojiSpans (nếu cần) và cuối cùng là hiển thị ký tự biểu tượng cảm xúc. Hình 2 minh hoạ quá trình này.

Quá trình hoạt động của EmojiCompat
Hình 2. Quá trình hoạt động của EmojiCompat

Cấu hình phông chữ có thể tải xuống

Cấu hình phông chữ có thể tải xuống sẽ sử dụng tính năng thư viện hỗ trợ phông chữ có thể tải xuống để tải xuống phông chữ biểu tượng cảm xúc. Nó cũng sẽ cập nhật siêu dữ liệu biểu tượng cảm xúc cần thiết mà thư viện hỗ trợ EmojiCompat cần để cập nhật các phiên bản mới nhất của thông số kỹ thuật Unicode.

Thêm phần phụ thuộc vào thư viện hỗ trợ

Để sử dụng thư viện hỗ trợ EmojiCompat, bạn phải chỉnh sửa các phần phụ thuộc classpath của dự án ứng dụng trong môi trường phát triển.

Để thêm thư viện hỗ trợ vào dự án ứng dụng, thực hiện các bước sau:

  1. Mở tệp build.gradle của ứng dụng.
  2. Thêm thư viện hỗ trợ vào phần dependencies.

Groovy

dependencies {
    ...
    implementation "androidx.emoji:emoji:28.0.0"
}

Kotlin

dependencies {
    ...
    implementation("androidx.emoji:emoji:28.0.0")
}

Khởi chạy cấu hình phông chữ có thể tải xuống

Bạn cần khởi chạy EmojiCompat để tải siêu dữ liệu và kiểu chữ. Vì quá trình khởi chạy có thể mất chút thời gian nên sẽ diễn ra trong một luồng nền.

Để khởi chạy EmojiCompat cho cấu hình phông chữ có thể tải xuống, hãy thực hiện các bước sau:

  1. Tạo một thực thể của lớp FontRequest và cấp quyền cho nhà cung cấp phông chữ, gói nhà cung cấp phông chữ, truy vấn phông chữ và danh sách các nhóm hàm băm cho chứng chỉ. Để biết thêm thông tin về FontRequest, tham khảo phần Sử dụng phông chữ có thể tải xuống theo phương thức lập trình trong tài liệu Phông chữ có thể tải xuống.
  2. Tạo một thực thể của FontRequestEmojiCompatConfig và cung cấp các thực thể của ContextFontRequest.
  3. Khởi chạy EmojiCompat bằng cách gọi phương thức init() và truyền thực thể FontRequestEmojiCompatConfig.
  4. Kotlin

    class MyApplication : Application() {
    
        override fun onCreate() {
            super.onCreate()
            val fontRequest = FontRequest(
                    "com.example.fontprovider",
                    "com.example",
                    "emoji compat Font Query",
                    CERTIFICATES
            )
            val config = FontRequestEmojiCompatConfig(this, fontRequest)
            EmojiCompat.init(config)
        }
    }
    

    Java

    public class MyApplication extends Application {
      @Override
       public void onCreate() {
         super.onCreate();
         FontRequest fontRequest = new FontRequest(
           "com.example.fontprovider",
           "com.example",
           "emoji compat Font Query",
           CERTIFICATES);
         EmojiCompat.Config config = new FontRequestEmojiCompatConfig(this, fontRequest);
         EmojiCompat.init(config);
       }
    }
    
  5. Sử dụng các tiện ích EmojiCompat trong XML bố cục. Nếu sử dụng AppCompat, tham khảo phần Sử dụng các tiện ích EmojiCompat với AppCompat.
  6. <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"/>
    

Để biết thêm thông tin về cách định cấu hình EmojiCompat với cấu hình phông chữ có thể tải xuống, xem bài viết Khả năng tương thích của biểu tượng cảm xúc trên ứng dụng mẫu trênJava | Kotlin.

Thành phần thư viện

Các thành phần thư viện trong quá trình hoạt động của EmojiCompat
Hình 3. Các thành phần thư viện trong quá trình hoạt động của EmojiCompat
Tiện ích: EmojiEditText, EmojiTextView, EmojiButton
Các biện pháp triển khai tiện ích mặc định để sử dụng EmojiCompat với TextView, EditTextButton.
EmojiCompat
Nền tảng công khai chính cho thư viện hỗ trợ. Nền tảng này thực hiện tất cả lệnh gọi bên ngoài và phối hợp với các phần khác của hệ thống.
EmojiCompat.Config
Định cấu hình cho thực thể singleton sẽ được tạo.
EmojiSpan
Một lớp con ReplacementSpan thay thế ký tự (trình tự) và kết xuất ký tự (glyph).
Phông chữ EmojiCompat
EmojiCompat sử dụng phông chữ để hiển thị biểu tượng cảm xúc. Phông chữ này là phiên bản đã chỉnh sửa của phông chữ biểu tượng cảm xúc Android. Phông chữ được chỉnh sửa như sau:
  • Để cung cấp khả năng tương thích ngược nhằm kết xuất biểu tượng cảm xúc, tất cả các ký tự biểu tượng cảm xúc đều được biểu thị bằng một điểm mã Unicode duy nhất trong phần Vùng riêng tư Area-A của Unicode bắt đầu bằng U+F0001.
  • Siêu dữ liệu về biểu tượng cảm xúc bổ sung được chèn vào phông chữ dưới định dạng tệp nhị phân và được EmojiCompat phân tích cú pháp trong thời gian chạy. Dữ liệu được nhúng trong bảng meta của phông chữ với thẻ riêng tư Emji.

Tuỳ chọn cấu hình

Bạn có thể sử dụng thực thể EmojiCompat để sửa đổi hành vi của EmojiCompat. Bạn có thể sử dụng các phương thức sau từ lớp cơ sở để thiết lập cấu hình:

Kotlin

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

Java

EmojiCompat.Config config = new FontRequestEmojiCompatConfig(...)
       .setReplaceAll(true)
       .setEmojiSpanIndicatorEnabled(true)
       .setEmojiSpanIndicatorColor(Color.GREEN)
       .registerInitCallback(new InitCallback() {...})

Thêm trình nghe khởi chạy

Các lớp EmojiCompatEmojiCompat cung cấp các phương thức registerInitCallback()unregisterInitCallback() để đăng ký lệnh gọi lại khởi chạy. Để sử dụng các phương thức này, hãy tạo một thực thể của lớp EmojiCompat.InitCallback. Gọi các phương thức này và truyền thực thể của lớp EmojiCompat.InitCallback. Khi khởi chạy thành công thư viện hỗ trợ EmojiCompat, lớp EmojiCompat sẽ gọi phương thức onInitialized(). Nếu không khởi chạy thành công thư viện, lớp EmojiCompat sẽ gọi phương thức onFailed().

Để kiểm tra trạng thái khởi chạy bất cứ lúc nào, gọi phương thức getLoadState(). Phương thức này trả về một trong các giá trị sau: LOAD_STATE_LOADING, LOAD_STATE_SUCCEEDED hoặc LOAD_STATE_FAILED.

Sử dụng EmojiCompat với các tiện ích AppCompat

Nếu đang sử dụng AppCompat widgets, bạn có thể sử dụng tiện ích EmojiCompat mở rộng từ AppCompat widgets.

  1. Thêm thư viện hỗ trợ vào các phần phụ thuộc.

    Groovy

    dependencies {
        ...
        implementation "androidx.emoji:emoji-bundled:$version"
    }
    

    Kotlin

          dependencies {
              implementation("androidx.emoji:emoji-appcompat:$version")
          }
          

    Groovy

          dependencies {
              implementation "androidx.emoji:emoji-appcompat:$version"
          }
          
  2. Sử dụng các tiện ích EmojiCompat AppCompat Widget trong XML bố cục.
  3. <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"/>
    

Cấu hình phông chữ theo gói

Thư viện hỗ trợ EmojiCompat cũng có sẵn trong phiên bản phông chữ theo gói. Gói này bao gồm phông chữ có siêu dữ liệu được nhúng. Gói này cũng chứa BundledEmojiCompatConfig mà sử dụng AssetManager để tải siêu dữ liệu và phông chữ.

Lưu ý: Kích thước của phông chữ sẽ tính bằng nhiều megabyte.

Thêm phần phụ thuộc vào thư viện hỗ trợ

Để sử dụng thư viện hỗ trợ EmojiCompat với cấu hình phông chữ theo gói, bạn phải chỉnh sửa các phần phụ thuộc classpath của dự án ứng dụng trong môi trường phát triển.

Để thêm thư viện hỗ trợ vào dự án ứng dụng, thực hiện các bước sau:

  1. Mở tệp build.gradle của ứng dụng.
  2. Thêm thư viện hỗ trợ vào phần dependencies.

Groovy

dependencies {
    ...
    implementation "androidx.emoji:emoji:28.0.0"
}

Kotlin

dependencies {
    ...
    implementation("androidx.emoji:emoji:28.0.0")
}

Sử dụng phông chữ theo gói để định cấu hình EmojiCompat

Để sử dụng phông chữ theo gói nhằm định cấu hình EmojiCompat, hãy làm theo các bước sau:

  1. Sử dụng BundledEmojiCompatConfig để tạo một thực thể của EmojiCompat và cung cấp một thực thể của Context.
  2. Gọi phương thức init() để khởi chạy EmojiCompat và truyền thực thể của BundledEmojiCompatConfig.

Kotlin

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        val config = BundledEmojiCompatConfig(this)
        EmojiCompat.init(config)
    }
}

Java

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
        EmojiCompat.init(config);
        ...
    }
}

Sử dụng EmojiCompat mà không cần tiện ích

EmojiCompat sử dụng EmojiSpan để kết xuất hình ảnh chính xác. Chính vì vậy mà nó phải chuyển đổi CharSequence bất kỳ thành các thực thể SpannedEmojiSpans. Lớp EmojiCompat cung cấp một phương thức để chuyển đổi CharSequences thành các thực thể SpannedEmojiSpans. Khi sử dụng phương thức này, bạn có thể xử lý và lưu các thực thể đã xử lý vào bộ nhớ đệm thay vì chuỗi thô, nhờ đó cải thiện hiệu suất của ứng dụng.

Kotlin

val processed = EmojiCompat.get().process("neutral face \uD83D\uDE10")

Java

CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");

Sử dụng EmojiCompat cho IME

Khi sử dụng thư viện hỗ trợ EmojiCompat, bàn phím có thể kết xuất biểu tượng cảm xúc mà ứng dụng đang tương tác hỗ trợ. IME có thể sử dụng phương thức hasEmojiGlyph() để kiểm tra xem EmojiCompat có thể kết xuất biểu tượng cảm xúc hay không. Phương thức này sẽ lấy CharSequence của biểu tượng cảm xúc và trả về true nếu EmojiCompat có thể phát hiện và kết xuất biểu tượng cảm xúc.

Bàn phím cũng có thể kiểm tra phiên bản thư viện hỗ trợ EmojiCompat mà ứng dụng hỗ trợ để xác định xem sẽ kết xuất biểu tượng cảm xúc nào trong bảng chế độ xem. Để kiểm tra phiên bản (nếu có), bàn phím cần kiểm tra xem các khoá sau có tồn tại trong gói EditorInfo.extras hay không:

Sau khi nhận được khoá trong gói EditorInfo.extras, bàn phím có thể sử dụng phương thức hasEmojiGlyph() (metadataVersion sẽ là giá trị choEDITOR_INFO_METAVERSION_KEY) để kiểm tra xem ứng dụng có thể kết xuất biểu tượng cảm xúc hay không.

Sử dụng EmojiCompat với các tiện ích tuỳ chỉnh

Bạn luôn có thể sử dụng phương thức process() để xử lý trước CharSequence trong ứng dụng và thêm phương thức này vào bất kỳ tiện ích nào có thể kết xuất các thực thể Spanned như TextView. Ngoài ra, EmojiCompat cung cấp các lớp của trình trợ giúp tiện ích sau đây để bạn có thể làm phong phú các tiện ích tuỳ chỉnh bằng biểu tượng cảm xúc mà không cần tốn quá nhiều công sức.

TextView mẫu

Kotlin

class MyTextView(context: Context) : AppCompatTextView(context) {

    private val emojiTextViewHelper: EmojiTextViewHelper by lazy(LazyThreadSafetyMode.NONE) {
        EmojiTextViewHelper(this).apply {
            updateTransformationMethod()
        }
    }

    override fun setFilters(filters: Array<InputFilter>) {
        super.setFilters(emojiTextViewHelper.getFilters(filters))
    }

    override fun setAllCaps(allCaps: Boolean) {
        super.setAllCaps(allCaps)
        emojiTextViewHelper.setAllCaps(allCaps)
    }
}

Java

public class MyTextView extends AppCompatTextView {
   ...
   public MyTextView(Context context) {
       super(context);
       init();
   }
   ...
   private void init() {
       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() {
       ...
   }
}
EditText mẫu

Kotlin

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
    }
}

Java

public class MyEditText extends AppCompatEditText {
   ...
   public MyEditText(Context context) {
       super(context);
       init();
   }
   ...
   private void init() {
       super.setKeyListener(getEmojiEditTextHelper().getKeyListener(getKeyListener()));
   }

   @Override
   public void setKeyListener(android.text.method.KeyListener keyListener) {
       super.setKeyListener(getEmojiEditTextHelper().getKeyListener(keyListener));
   }

   @Override
   public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
       InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
       return getEmojiEditTextHelper().onCreateInputConnection(inputConnection, outAttrs);
   }

   private EmojiEditTextHelper getEmojiEditTextHelper() {
       ...
   }
}

Câu hỏi thường gặp

  • Làm cách nào để bắt đầu tải phông chữ xuống?
  • Phông chữ biểu tượng cảm xúc được tải xuống khi được yêu cầu lần đầu với điều kiện là thiết bị chưa có các biểu tượng đó. Lịch tải xuống minh bạch với ứng dụng.

  • Thời gian khởi chạy là bao lâu?
  • Sau khi tải xuống phông chữ, bạn sẽ mất khoảng 150 mili giây để khởi chạy EmojiCompat.

  • Thư viện hỗ trợ EmojiCompat sử dụng bao nhiêu bộ nhớ?
  • Hiện tại, cấu trúc dữ liệu để tìm biểu tượng cảm xúc được tải trong bộ nhớ của ứng dụng và sử dụng khoảng 200KB.

  • Tôi có thể sử dụng EmojiCompat cho TextView tuỳ chỉnh không?
  • Có. EmojiCompat cung cấp các lớp trợ giúp cho các tiện ích tuỳ chỉnh. Bạn cũng có thể xử lý trước một chuỗi được cung cấp và chuyển đổi chuỗi đó thành Spanned. Để biết thêm thông tin về các lớp của trình trợ giúp tiện ích, hãy tham khảo phần Sử dụng EmojiCompat với các tiện ích tuỳ chỉnh.

  • Điều gì xảy ra nếu tôi thêm tiện ích trong XML bố cục trên các thiết bị chạy trên Android 4.4 (API cấp 19) trở xuống?
  • Bạn có thể đưa thư viện hỗ trợ EmojiCompat hoặc các tiện ích của thư viện đó vào những ứng dụng hỗ trợ thiết bị chạy Android 4.4 (API cấp 19) trở xuống. Tuy nhiên, nếu thiết bị chạy trên một phiên bản Android có API trước API cấp 19, thì EmojiCompat và các tiện ích của thiết bị này sẽ ở trạng thái "không hoạt động". Điều này có nghĩa là EmojiTextView sẽ hoạt động giống như TextView thông thường. Thực thể EmojiCompat; thực thể này sẽ chuyển sang trạng thái LOAD_STATE_SUCCEEDED ngay lập tức khi gọi phương thức init().

Tài nguyên khác

Để biết thêm thông tin về cách sử dụng thư viện EmojiCompat, hãy xem EmojiCompat.