public abstract class

EmojiSpan

extends ReplacementSpan

 java.lang.Object

↳ReplacementSpan

↳androidx.emoji2.text.EmojiSpan

Subclasses:

TypefaceEmojiSpan

Gradle dependencies

compile group: 'androidx.emoji2', name: 'emoji2', version: '1.2.0-alpha04'

  • groupId: androidx.emoji2
  • artifactId: emoji2
  • version: 1.2.0-alpha04

Artifact androidx.emoji2:emoji2:1.2.0-alpha04 it located at Google repository (https://maven.google.com/)

Overview

Base span class for the emoji replacement. When an emoji is found and needs to be replaced in a CharSequence, an instance of this class is added to the CharSequence.

Summary

Methods
public final intgetHeight()

public final intgetId()

public final EmojiMetadatagetMetadata()

public intgetSize(Paint paint, java.lang.CharSequence text, int start, int end, Paint.FontMetricsInt fm)

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public int getSize(Paint paint, java.lang.CharSequence text, int start, int end, Paint.FontMetricsInt fm)

public final EmojiMetadata getMetadata()

public final int getHeight()

Returns:

height of the span

public final int getId()

Returns:

unique id for the emoji that this EmojiSpan is used for

Source

/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.emoji2.text;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static androidx.annotation.RestrictTo.Scope.TESTS;

import android.annotation.SuppressLint;
import android.graphics.Paint;
import android.text.style.ReplacementSpan;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.util.Preconditions;

/**
 * Base span class for the emoji replacement. When an emoji is found and needs to be replaced in a
 * CharSequence, an instance of this class is added to the CharSequence.
 */
@RequiresApi(19)
public abstract class EmojiSpan extends ReplacementSpan {

    /**
     * Temporary object to calculate the size of the span.
     */
    private final Paint.FontMetricsInt mTmpFontMetrics = new Paint.FontMetricsInt();

    /**
     * Information about emoji. This is not parcelled since we do not want multiple objects
     * representing same emoji to be in memory. When unparcelled, EmojiSpan tries to set it back
     * using the singleton EmojiCompat instance.
     */
    @NonNull
    private final EmojiMetadata mMetadata;

    /**
     * Cached width of the span. Width is calculated according to the font metrics.
     */
    private short mWidth = -1;

    /**
     * Cached height of the span. Height is calculated according to the font metrics.
     */
    private short mHeight = -1;

    /**
     * Cached ratio of current font height to emoji image height.
     */
    private float mRatio = 1.0f;

    /**
     * Default constructor.
     *
     * @param metadata information about the emoji, cannot be {@code null}
     *
     * @hide
     */
    @RestrictTo(LIBRARY)
    EmojiSpan(@NonNull final EmojiMetadata metadata) {
        Preconditions.checkNotNull(metadata, "metadata cannot be null");
        mMetadata = metadata;
    }

    @Override
    public int getSize(@NonNull final Paint paint,
            @SuppressLint("UnknownNullness") @SuppressWarnings("MissingNullability")
            final CharSequence text,
            final int start,
            final int end,
            @Nullable final Paint.FontMetricsInt fm) {
        paint.getFontMetricsInt(mTmpFontMetrics);
        final int fontHeight = Math.abs(mTmpFontMetrics.descent - mTmpFontMetrics.ascent);

        mRatio = fontHeight * 1.0f / mMetadata.getHeight();
        mHeight = (short) (mMetadata.getHeight() * mRatio);
        mWidth = (short) (mMetadata.getWidth() * mRatio);

        if (fm != null) {
            fm.ascent = mTmpFontMetrics.ascent;
            fm.descent = mTmpFontMetrics.descent;
            fm.top = mTmpFontMetrics.top;
            fm.bottom = mTmpFontMetrics.bottom;
        }

        return mWidth;
    }

    /**
     * @hide
     */
    @NonNull
    @RestrictTo(LIBRARY_GROUP)
    public final EmojiMetadata getMetadata() {
        return mMetadata;
    }

    /**
     * @return width of the span
     *
     * @hide
     */
    @RestrictTo(LIBRARY)
    final int getWidth() {
        return mWidth;
    }

    /**
     * @return height of the span
     *
     * @hide
     */
    @RestrictTo(TESTS)
    public final int getHeight() {
        return mHeight;
    }

    /**
     * @hide
     */
    @RestrictTo(LIBRARY)
    final float getRatio() {
        return mRatio;
    }

    /**
     * @return unique id for the emoji that this EmojiSpan is used for
     *
     * @hide
     */
    @RestrictTo(TESTS)
    public final int getId() {
        return getMetadata().getId();
    }
}