java.lang.Object

↳TextView

↳androidx.appcompat.widget.AppCompatTextView

Subclasses:

ActionMenuItemView, DialogTitle, EmojiAppCompatTextView

Gradle dependencies

compile group: 'androidx.appcompat', name: 'appcompat', version: '1.7.0'

  • groupId: androidx.appcompat
  • artifactId: appcompat
  • version: 1.7.0

Artifact androidx.appcompat:appcompat:1.7.0 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.appcompat:appcompat com.android.support:appcompat-v7

Androidx class mapping:

androidx.appcompat.widget.AppCompatTextView android.support.v7.widget.AppCompatTextView

Overview

A TextView which supports compatible features on older versions of the platform, including:

  • Allows dynamic tint of its background via the background tint methods in ViewCompat.
  • Allows setting of the background tint using and .
  • Supports auto-sizing via TextViewCompat by allowing to instruct a TextView to let the size of the text expand or contract automatically to fill its layout based on the TextView's characteristics and boundaries. The style attributes associated with auto-sizing are , , , and , all of which work back to .

This will automatically be used when you use TextView in your layouts and the top-level activity / dialog is provided by appcompat. You should only need to manually use this class when writing custom views.

Summary

Constructors
publicAppCompatTextView(Context context)

publicAppCompatTextView(Context context, AttributeSet attrs)

publicAppCompatTextView(Context context, AttributeSet attrs, int defStyleAttr)

Methods
protected voiddrawableStateChanged()

public intgetAutoSizeMaxTextSize()

This should be accessed via TextViewCompat.getAutoSizeMaxTextSize(TextView)

public intgetAutoSizeMinTextSize()

This should be accessed via TextViewCompat.getAutoSizeMinTextSize(TextView)

public intgetAutoSizeStepGranularity()

This should be accessed via TextViewCompat.getAutoSizeStepGranularity(TextView)

public int[]getAutoSizeTextAvailableSizes()

This should be accessed via TextViewCompat.getAutoSizeTextAvailableSizes(TextView)

public intgetAutoSizeTextType()

This should be accessed via TextViewCompat.getAutoSizeTextType(TextView)

public ActionMode.CallbackgetCustomSelectionActionModeCallback()

public intgetFirstBaselineToTopHeight()

public intgetLastBaselineToBottomHeight()

public ColorStateListgetSupportBackgroundTintList()

This should be accessed via ViewCompat

public PorterDuff.ModegetSupportBackgroundTintMode()

This should be accessed via ViewCompat

public ColorStateListgetSupportCompoundDrawablesTintList()

This should be accessed via TextViewCompat.getCompoundDrawableTintList(TextView)

public PorterDuff.ModegetSupportCompoundDrawablesTintMode()

This should be accessed via TextViewCompat.getCompoundDrawableTintMode(TextView) Returns the blending mode used to apply the tint to the compound drawables, if specified.

public java.lang.CharSequencegetText()

public TextClassifiergetTextClassifier()

Returns the used by this TextView.

public PrecomputedTextCompat.ParamsgetTextMetricsParamsCompat()

Gets the parameters for text layout precomputation, for use with PrecomputedTextCompat.

public booleanisEmojiCompatEnabled()

public InputConnectiononCreateInputConnection(EditorInfo outAttrs)

protected voidonDetachedFromWindow()

protected voidonLayout(boolean changed, int left, int top, int right, int bottom)

protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

protected voidonTextChanged(java.lang.CharSequence text, int start, int lengthBefore, int lengthAfter)

public voidsetAllCaps(boolean allCaps)

public voidsetAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize, int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit)

This should be accessed via TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(TextView, int, int, int, int)

public voidsetAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes[], int unit)

This should be accessed via TextViewCompat.setAutoSizeTextTypeUniformWithPresetSizes(TextView, int[], int)

public voidsetAutoSizeTextTypeWithDefaults(int autoSizeTextType)

This should be accessed via TextViewCompat.setAutoSizeTextTypeWithDefaults(TextView, int)

public voidsetBackgroundDrawable(Drawable background)

public voidsetBackgroundResource(int resId)

public voidsetCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)

public voidsetCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom)

public voidsetCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom)

public voidsetCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom)

public voidsetCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback)

See TextViewCompat.setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)

public voidsetEmojiCompatEnabled(boolean enabled)

public voidsetFilters(InputFilter filters[])

public voidsetFirstBaselineToTopHeight(int firstBaselineToTopHeight)

public voidsetLastBaselineToBottomHeight(int lastBaselineToBottomHeight)

public voidsetLineHeight(int lineHeight)

public voidsetLineHeight(int unit, float lineHeight)

public voidsetPrecomputedText(PrecomputedTextCompat precomputed)

Sets the PrecomputedTextCompat to the TextView.

public voidsetSupportBackgroundTintList(ColorStateList tint)

This should be accessed via ViewCompat

public voidsetSupportBackgroundTintMode(PorterDuff.Mode tintMode)

This should be accessed via ViewCompat

public voidsetSupportCompoundDrawablesTintList(ColorStateList tintList)

This should be accessed via TextViewCompat.setCompoundDrawableTintList(TextView, ColorStateList) Applies a tint to the compound drawables.

public voidsetSupportCompoundDrawablesTintMode(PorterDuff.Mode tintMode)

This should be accessed via TextViewCompat.setCompoundDrawableTintMode(TextView, PorterDuff.Mode) Specifies the blending mode used to apply the tint specified by AppCompatTextView.setSupportCompoundDrawablesTintList(ColorStateList) to the compound drawables.

public voidsetTextAppearance(Context context, int resId)

public voidsetTextClassifier(TextClassifier textClassifier)

Sets the for this TextView.

public voidsetTextFuture(java.util.concurrent.Future<PrecomputedTextCompat> future)

Set the precomputed text future.

public voidsetTextMetricsParamsCompat(PrecomputedTextCompat.Params params)

Apply the text layout parameter.

public voidsetTextSize(int unit, float size)

public voidsetTypeface(Typeface tf, int style)

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

Constructors

public AppCompatTextView(Context context)

public AppCompatTextView(Context context, AttributeSet attrs)

public AppCompatTextView(Context context, AttributeSet attrs, int defStyleAttr)

Methods

public void setBackgroundResource(int resId)

public void setBackgroundDrawable(Drawable background)

public void setSupportBackgroundTintList(ColorStateList tint)

This should be accessed via ViewCompat

public ColorStateList getSupportBackgroundTintList()

This should be accessed via ViewCompat

public void setSupportBackgroundTintMode(PorterDuff.Mode tintMode)

This should be accessed via ViewCompat

public PorterDuff.Mode getSupportBackgroundTintMode()

This should be accessed via ViewCompat

public void setTextAppearance(Context context, int resId)

public void setFilters(InputFilter filters[])

public void setAllCaps(boolean allCaps)

public void setEmojiCompatEnabled(boolean enabled)

public boolean isEmojiCompatEnabled()

protected void drawableStateChanged()

protected void onLayout(boolean changed, int left, int top, int right, int bottom)

public void setTextSize(int unit, float size)

protected void onTextChanged(java.lang.CharSequence text, int start, int lengthBefore, int lengthAfter)

public void setAutoSizeTextTypeWithDefaults(int autoSizeTextType)

This should be accessed via TextViewCompat.setAutoSizeTextTypeWithDefaults(TextView, int)

public void setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize, int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit)

This should be accessed via TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(TextView, int, int, int, int)

public void setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes[], int unit)

This should be accessed via TextViewCompat.setAutoSizeTextTypeUniformWithPresetSizes(TextView, int[], int)

public int getAutoSizeTextType()

This should be accessed via TextViewCompat.getAutoSizeTextType(TextView)

public int getAutoSizeStepGranularity()

This should be accessed via TextViewCompat.getAutoSizeStepGranularity(TextView)

public int getAutoSizeMinTextSize()

This should be accessed via TextViewCompat.getAutoSizeMinTextSize(TextView)

public int getAutoSizeMaxTextSize()

This should be accessed via TextViewCompat.getAutoSizeMaxTextSize(TextView)

public int[] getAutoSizeTextAvailableSizes()

This should be accessed via TextViewCompat.getAutoSizeTextAvailableSizes(TextView)

public InputConnection onCreateInputConnection(EditorInfo outAttrs)

public void setFirstBaselineToTopHeight(int firstBaselineToTopHeight)

public void setLastBaselineToBottomHeight(int lastBaselineToBottomHeight)

public int getFirstBaselineToTopHeight()

public int getLastBaselineToBottomHeight()

public void setLineHeight(int lineHeight)

public void setLineHeight(int unit, float lineHeight)

public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback)

See TextViewCompat.setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)

public ActionMode.Callback getCustomSelectionActionModeCallback()

public PrecomputedTextCompat.Params getTextMetricsParamsCompat()

Gets the parameters for text layout precomputation, for use with PrecomputedTextCompat.

Returns:

a current

See also: PrecomputedTextCompat

public void setTextMetricsParamsCompat(PrecomputedTextCompat.Params params)

Apply the text layout parameter. Update the TextView parameters to be compatible with .

See also: PrecomputedTextCompat

public void setPrecomputedText(PrecomputedTextCompat precomputed)

Sets the PrecomputedTextCompat to the TextView. If the given PrecomputeTextCompat is not compatible with textView, throws an IllegalArgumentException.

Parameters:

precomputed: the precomputed text

public java.lang.CharSequence getText()

public void setTextClassifier(TextClassifier textClassifier)

Sets the for this TextView.

public TextClassifier getTextClassifier()

Returns the used by this TextView. If no TextClassifier has been set, this TextView uses the default set by the .

public void setTextFuture(java.util.concurrent.Future<PrecomputedTextCompat> future)

Set the precomputed text future. This method sets future of the precomputed text instead of immediately applying text to the TextView. Anything layout related property changes, text size, typeface, letter spacing, etc after this method call will causes IllegalArgumentException during View measurement. See PrecomputedTextCompat.getTextFuture(CharSequence, PrecomputedTextCompat.Params, Executor) for more detail.

Parameters:

future: a future for the precomputed text

See also: PrecomputedTextCompat.getTextFuture(CharSequence, PrecomputedTextCompat.Params, Executor)

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)

public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom)

public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom)

public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom)

public ColorStateList getSupportCompoundDrawablesTintList()

This should be accessed via TextViewCompat.getCompoundDrawableTintList(TextView)

Returns:

the tint applied to the compound drawables

See also: AppCompatTextView.setSupportCompoundDrawablesTintList(ColorStateList)

public void setSupportCompoundDrawablesTintList(ColorStateList tintList)

This should be accessed via TextViewCompat.setCompoundDrawableTintList(TextView, ColorStateList) Applies a tint to the compound drawables. Does not modify the current tint mode, which is by default.

Subsequent calls to AppCompatTextView.setCompoundDrawables(Drawable, Drawable, Drawable, Drawable) and related methods will automatically mutate the drawables and apply the specified tint and tint mode using Drawable.

Parameters:

tintList: the tint to apply, may be null to clear tint

See also: AppCompatTextView.getSupportCompoundDrawablesTintList()

public PorterDuff.Mode getSupportCompoundDrawablesTintMode()

This should be accessed via TextViewCompat.getCompoundDrawableTintMode(TextView) Returns the blending mode used to apply the tint to the compound drawables, if specified.

Returns:

the blending mode used to apply the tint to the compound drawables

See also: AppCompatTextView.setSupportCompoundDrawablesTintMode(PorterDuff.Mode)

public void setSupportCompoundDrawablesTintMode(PorterDuff.Mode tintMode)

This should be accessed via TextViewCompat.setCompoundDrawableTintMode(TextView, PorterDuff.Mode) Specifies the blending mode used to apply the tint specified by AppCompatTextView.setSupportCompoundDrawablesTintList(ColorStateList) to the compound drawables. The default mode is .

Parameters:

tintMode: the blending mode used to apply the tint, may be null to clear tint

See also: AppCompatTextView.setSupportCompoundDrawablesTintList(ColorStateList)

public void setTypeface(Typeface tf, int style)

protected void onDetachedFromWindow()

Source

/*
 * Copyright (C) 2015 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.appcompat.widget;

import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
import static androidx.appcompat.widget.ViewUtils.SDK_LEVEL_SUPPORTS_AUTOSIZE;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.text.InputFilter;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.textclassifier.TextClassifier;
import android.widget.TextView;

import androidx.annotation.DrawableRes;
import androidx.annotation.FloatRange;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.annotation.UiThread;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.graphics.TypefaceCompat;
import androidx.core.text.PrecomputedTextCompat;
import androidx.core.view.TintableBackgroundView;
import androidx.core.widget.AutoSizeableTextView;
import androidx.core.widget.TextViewCompat;
import androidx.core.widget.TintableCompoundDrawablesView;
import androidx.resourceinspection.annotation.AppCompatShadowedAttributes;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * A {@link TextView} which supports compatible features on older versions of the platform,
 * including:
 * <ul>
 * <li>Allows dynamic tint of its background via the background tint methods in
 * {@link androidx.core.view.ViewCompat}.</li>
 * <li>Allows setting of the background tint using
 * {@link androidx.appcompat.R.attr#backgroundTint} and
 * {@link androidx.appcompat.R.attr#backgroundTintMode}.</li>
 * <li>Supports auto-sizing via {@link androidx.core.widget.TextViewCompat} by allowing to instruct
 * a {@link TextView} to let the size of the text expand or contract automatically to fill its
 * layout based on the TextView's characteristics and boundaries. The style attributes associated
 * with auto-sizing are
 * {@link androidx.appcompat.R.attr#autoSizeTextType},
 * {@link androidx.appcompat.R.attr#autoSizeMinTextSize},
 * {@link androidx.appcompat.R.attr#autoSizeMaxTextSize},
 * {@link androidx.appcompat.R.attr#autoSizeStepGranularity} and
 * {@link androidx.appcompat.R.attr#autoSizePresetSizes}, all of which work back to
 * {@link VERSION_CODES#ICE_CREAM_SANDWICH Ice Cream Sandwich}.</li>
 * </ul>
 *
 * <p>This will automatically be used when you use {@link TextView} in your layouts
 * and the top-level activity / dialog is provided by
 * <a href="{@docRoot}topic/libraries/support-library/packages.html#v7-appcompat">appcompat</a>.
 * You should only need to manually use this class when writing custom views.</p>
 */
@AppCompatShadowedAttributes
public class AppCompatTextView extends TextView implements TintableBackgroundView,
        TintableCompoundDrawablesView, AutoSizeableTextView, EmojiCompatConfigurationView {

    private final AppCompatBackgroundHelper mBackgroundTintHelper;
    private final AppCompatTextHelper mTextHelper;
    private final AppCompatTextClassifierHelper mTextClassifierHelper;
    @SuppressWarnings("NotNullFieldNotInitialized") // initialized in getter
    @NonNull
    private AppCompatEmojiTextHelper mEmojiTextViewHelper;

    private boolean mIsSetTypefaceProcessing = false;

    @Nullable
    private SuperCaller mSuperCaller = null;

    @Nullable
    private Future<PrecomputedTextCompat> mPrecomputedTextFuture;

    public AppCompatTextView(@NonNull Context context) {
        this(context, null);
    }

    public AppCompatTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public AppCompatTextView(
            @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(TintContextWrapper.wrap(context), attrs, defStyleAttr);

        ThemeUtils.checkAppCompatTheme(this, getContext());

        mBackgroundTintHelper = new AppCompatBackgroundHelper(this);
        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);

        mTextHelper = new AppCompatTextHelper(this);
        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
        mTextHelper.applyCompoundDrawablesTints();

        mTextClassifierHelper = new AppCompatTextClassifierHelper(this);

        AppCompatEmojiTextHelper emojiTextViewHelper = getEmojiTextViewHelper();
        emojiTextViewHelper.loadFromAttributes(attrs, defStyleAttr);
    }

    /**
     * This may be called from super constructors.
     */
    @NonNull
    private AppCompatEmojiTextHelper getEmojiTextViewHelper() {
        //noinspection ConstantConditions
        if (mEmojiTextViewHelper == null) {
            mEmojiTextViewHelper = new AppCompatEmojiTextHelper(this);
        }
        return mEmojiTextViewHelper;
    }

    @Override
    public void setBackgroundResource(@DrawableRes int resId) {
        super.setBackgroundResource(resId);
        if (mBackgroundTintHelper != null) {
            mBackgroundTintHelper.onSetBackgroundResource(resId);
        }
    }

    @Override
    public void setBackgroundDrawable(@Nullable Drawable background) {
        super.setBackgroundDrawable(background);
        if (mBackgroundTintHelper != null) {
            mBackgroundTintHelper.onSetBackgroundDrawable(background);
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
        if (mBackgroundTintHelper != null) {
            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.view.ViewCompat#getBackgroundTintList(android.view.View)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    @Nullable
    public ColorStateList getSupportBackgroundTintList() {
        return mBackgroundTintHelper != null
                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
    }

    /**
     * This should be accessed via
     * {@link androidx.core.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
        if (mBackgroundTintHelper != null) {
            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.view.ViewCompat#getBackgroundTintMode(android.view.View)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    @Nullable
    public PorterDuff.Mode getSupportBackgroundTintMode() {
        return mBackgroundTintHelper != null
                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
    }

    @Override
    public void setTextAppearance(Context context, int resId) {
        super.setTextAppearance(context, resId);
        if (mTextHelper != null) {
            mTextHelper.onSetTextAppearance(context, resId);
        }
    }

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

    @Override
    public void setAllCaps(boolean allCaps) {
        super.setAllCaps(allCaps);
        getEmojiTextViewHelper().setAllCaps(allCaps);
    }

    @Override
    public void setEmojiCompatEnabled(boolean enabled) {
        getEmojiTextViewHelper().setEnabled(enabled);
    }

    @Override
    public boolean isEmojiCompatEnabled() {
        return getEmojiTextViewHelper().isEnabled();
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (mBackgroundTintHelper != null) {
            mBackgroundTintHelper.applySupportBackgroundTint();
        }
        if (mTextHelper != null) {
            mTextHelper.applyCompoundDrawablesTints();
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (mTextHelper != null) {
            mTextHelper.onLayout(changed, left, top, right, bottom);
        }
    }

    @Override
    public void setTextSize(int unit, float size) {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            super.setTextSize(unit, size);
        } else {
            if (mTextHelper != null) {
                mTextHelper.setTextSize(unit, size);
            }
        }
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        boolean useHelper = mTextHelper != null && !SDK_LEVEL_SUPPORTS_AUTOSIZE
                && mTextHelper.isAutoSizeEnabled();
        if (useHelper) {
            mTextHelper.autoSizeText();
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#setAutoSizeTextTypeWithDefaults(
     *TextView, int)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public void setAutoSizeTextTypeWithDefaults(
            @TextViewCompat.AutoSizeTextType int autoSizeTextType) {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            getSuperCaller().setAutoSizeTextTypeWithDefaults(autoSizeTextType);
        } else {
            if (mTextHelper != null) {
                mTextHelper.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
            }
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#setAutoSizeTextTypeUniformWithConfiguration(
     *TextView, int, int, int, int)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public void setAutoSizeTextTypeUniformWithConfiguration(
            int autoSizeMinTextSize,
            int autoSizeMaxTextSize,
            int autoSizeStepGranularity,
            int unit) throws IllegalArgumentException {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            getSuperCaller().setAutoSizeTextTypeUniformWithConfiguration(autoSizeMinTextSize,
                    autoSizeMaxTextSize, autoSizeStepGranularity, unit);
        } else {
            if (mTextHelper != null) {
                mTextHelper.setAutoSizeTextTypeUniformWithConfiguration(
                        autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
            }
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#setAutoSizeTextTypeUniformWithPresetSizes(
     *TextView, int[], int)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull int[] presetSizes, int unit)
            throws IllegalArgumentException {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            getSuperCaller().setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
        } else {
            if (mTextHelper != null) {
                mTextHelper.setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
            }
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getAutoSizeTextType(TextView)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    @TextViewCompat.AutoSizeTextType
    // Suppress lint error for TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM [WrongConstant]
    @SuppressLint("WrongConstant")
    public int getAutoSizeTextType() {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            return getSuperCaller().getAutoSizeTextType() == TextView
                    .AUTO_SIZE_TEXT_TYPE_UNIFORM
                    ? TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM
                    : TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
        } else {
            if (mTextHelper != null) {
                return mTextHelper.getAutoSizeTextType();
            }
        }
        return TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getAutoSizeStepGranularity(TextView)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public int getAutoSizeStepGranularity() {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            return getSuperCaller().getAutoSizeStepGranularity();
        } else {
            if (mTextHelper != null) {
                return mTextHelper.getAutoSizeStepGranularity();
            }
        }
        return -1;
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getAutoSizeMinTextSize(TextView)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public int getAutoSizeMinTextSize() {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            return getSuperCaller().getAutoSizeMinTextSize();
        } else {
            if (mTextHelper != null) {
                return mTextHelper.getAutoSizeMinTextSize();
            }
        }
        return -1;
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getAutoSizeMaxTextSize(TextView)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public int getAutoSizeMaxTextSize() {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            return getSuperCaller().getAutoSizeMaxTextSize();
        } else {
            if (mTextHelper != null) {
                return mTextHelper.getAutoSizeMaxTextSize();
            }
        }
        return -1;
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getAutoSizeTextAvailableSizes(TextView)}
     *
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @Override
    public int[] getAutoSizeTextAvailableSizes() {
        if (SDK_LEVEL_SUPPORTS_AUTOSIZE) {
            return getSuperCaller().getAutoSizeTextAvailableSizes();
        } else {
            if (mTextHelper != null) {
                return mTextHelper.getAutoSizeTextAvailableSizes();
            }
        }
        return new int[0];
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection ic = super.onCreateInputConnection(outAttrs);
        mTextHelper.populateSurroundingTextIfNeeded(this, ic, outAttrs);
        return AppCompatHintHelper.onCreateInputConnection(ic, outAttrs, this);
    }

    @Override
    public void setFirstBaselineToTopHeight(@Px @IntRange(from = 0) int firstBaselineToTopHeight) {
        if (Build.VERSION.SDK_INT >= 28) {
            getSuperCaller().setFirstBaselineToTopHeight(firstBaselineToTopHeight);
        } else {
            TextViewCompat.setFirstBaselineToTopHeight(this, firstBaselineToTopHeight);
        }
    }

    @Override
    public void setLastBaselineToBottomHeight(
            @Px @IntRange(from = 0) int lastBaselineToBottomHeight) {
        if (Build.VERSION.SDK_INT >= 28) {
            getSuperCaller().setLastBaselineToBottomHeight(lastBaselineToBottomHeight);
        } else {
            TextViewCompat.setLastBaselineToBottomHeight(this,
                    lastBaselineToBottomHeight);
        }
    }

    @Override
    public int getFirstBaselineToTopHeight() {
        return TextViewCompat.getFirstBaselineToTopHeight(this);
    }

    @Override
    public int getLastBaselineToBottomHeight() {
        return TextViewCompat.getLastBaselineToBottomHeight(this);
    }

    @Override
    public void setLineHeight(@Px @IntRange(from = 0) int lineHeight) {
        TextViewCompat.setLineHeight(this, lineHeight);
    }

    @Override
    public void setLineHeight(int unit, @FloatRange(from = 0) float lineHeight) {
        if (Build.VERSION.SDK_INT >= 34) {
            getSuperCaller().setLineHeight(unit, lineHeight);
        } else {
            TextViewCompat.setLineHeight(this, unit, lineHeight);
        }
    }

    /**
     * See
     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
     */
    @Override
    public void setCustomSelectionActionModeCallback(
            @Nullable ActionMode.Callback actionModeCallback) {
        super.setCustomSelectionActionModeCallback(
                TextViewCompat.wrapCustomSelectionActionModeCallback(this, actionModeCallback));
    }

    @Override
    @Nullable
    public ActionMode.Callback getCustomSelectionActionModeCallback() {
        return TextViewCompat.unwrapCustomSelectionActionModeCallback(
                super.getCustomSelectionActionModeCallback());
    }

    /**
     * Gets the parameters for text layout precomputation, for use with
     * {@link PrecomputedTextCompat}.
     *
     * @return a current {@link PrecomputedTextCompat.Params}
     * @see PrecomputedTextCompat
     */
    @NonNull
    public PrecomputedTextCompat.Params getTextMetricsParamsCompat() {
        return TextViewCompat.getTextMetricsParams(this);
    }

    /**
     * Apply the text layout parameter.
     *
     * Update the TextView parameters to be compatible with {@link PrecomputedTextCompat.Params}.
     *
     * @see PrecomputedTextCompat
     */
    public void setTextMetricsParamsCompat(@NonNull PrecomputedTextCompat.Params params) {
        TextViewCompat.setTextMetricsParams(this, params);
    }

    /**
     * Sets the PrecomputedTextCompat to the TextView.
     *
     * If the given PrecomputeTextCompat is not compatible with textView, throws an
     * IllegalArgumentException.
     *
     * @param precomputed the precomputed text
     * @throws IllegalArgumentException if precomputed text is not compatible with textView.
     */
    public void setPrecomputedText(@NonNull PrecomputedTextCompat precomputed) {
        TextViewCompat.setPrecomputedText(this, precomputed);
    }

    private void consumeTextFutureAndSetBlocking() {
        if (mPrecomputedTextFuture != null) {
            try {
                Future<PrecomputedTextCompat> future = mPrecomputedTextFuture;
                mPrecomputedTextFuture = null;
                TextViewCompat.setPrecomputedText(this, future.get());
            } catch (InterruptedException | ExecutionException e) {
                // ignore
            }
        }
    }

    @Override
    public CharSequence getText() {
        consumeTextFutureAndSetBlocking();
        return super.getText();
    }

    /**
     * Sets the {@link TextClassifier} for this TextView.
     */
    @Override
    @RequiresApi(api = 26)
    public void setTextClassifier(@Nullable TextClassifier textClassifier) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P || mTextClassifierHelper == null) {
            getSuperCaller().setTextClassifier(textClassifier);
            return;
        }
        mTextClassifierHelper.setTextClassifier(textClassifier);
    }

    /**
     * Returns the {@link TextClassifier} used by this TextView.
     * If no TextClassifier has been set, this TextView uses the default set by the
     * {@link android.view.textclassifier.TextClassificationManager}.
     */
    @Override
    @RequiresApi(api = 26)
    @NonNull
    public TextClassifier getTextClassifier() {
        // The null check is necessary because getTextClassifier is called when we are invoking
        // the super class's constructor.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P || mTextClassifierHelper == null) {
            return getSuperCaller().getTextClassifier();
        }
        return mTextClassifierHelper.getTextClassifier();
    }

    /**
     * Set the precomputed text future.
     *
     * This method sets future of the precomputed text instead of immediately applying text to the
     * TextView. Anything layout related property changes, text size, typeface, letter spacing, etc
     * after this method call will causes IllegalArgumentException during View measurement.
     *
     * See {@link PrecomputedTextCompat#getTextFuture} for more detail.
     *
     * @param future a future for the precomputed text
     * @see PrecomputedTextCompat#getTextFuture
     */
    public void setTextFuture(@Nullable Future<PrecomputedTextCompat> future) {
        mPrecomputedTextFuture = future;
        if (future != null) {
            requestLayout();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        consumeTextFutureAndSetBlocking();
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void setCompoundDrawables(@Nullable Drawable left, @Nullable Drawable top,
            @Nullable Drawable right, @Nullable Drawable bottom) {
        super.setCompoundDrawables(left, top, right, bottom);
        if (mTextHelper != null) {
            mTextHelper.onSetCompoundDrawables();
        }
    }

    @Override
    public void setCompoundDrawablesRelative(@Nullable Drawable start, @Nullable Drawable top,
            @Nullable Drawable end, @Nullable Drawable bottom) {
        super.setCompoundDrawablesRelative(start, top, end, bottom);
        if (mTextHelper != null) {
            mTextHelper.onSetCompoundDrawables();
        }
    }

    @Override
    public void setCompoundDrawablesWithIntrinsicBounds(@Nullable Drawable left,
            @Nullable Drawable top, @Nullable Drawable right, @Nullable Drawable bottom) {
        super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
        if (mTextHelper != null) {
            mTextHelper.onSetCompoundDrawables();
        }
    }

    @Override
    public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
        final Context context = getContext();
        setCompoundDrawablesWithIntrinsicBounds(
                left != 0 ? AppCompatResources.getDrawable(context, left) : null,
                top != 0 ? AppCompatResources.getDrawable(context, top) : null,
                right != 0 ? AppCompatResources.getDrawable(context, right) : null,
                bottom != 0 ? AppCompatResources.getDrawable(context, bottom) : null);
        if (mTextHelper != null) {
            mTextHelper.onSetCompoundDrawables();
        }
    }

    @Override
    public void setCompoundDrawablesRelativeWithIntrinsicBounds(@Nullable Drawable start,
            @Nullable Drawable top, @Nullable Drawable end, @Nullable Drawable bottom) {
        super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
        if (mTextHelper != null) {
            mTextHelper.onSetCompoundDrawables();
        }
    }

    @Override
    public void setCompoundDrawablesRelativeWithIntrinsicBounds(
            int start, int top, int end, int bottom) {
        final Context context = getContext();
        setCompoundDrawablesRelativeWithIntrinsicBounds(
                start != 0 ? AppCompatResources.getDrawable(context, start) : null,
                top != 0 ? AppCompatResources.getDrawable(context, top) : null,
                end != 0 ? AppCompatResources.getDrawable(context, end) : null,
                bottom != 0 ? AppCompatResources.getDrawable(context, bottom) : null);
        if (mTextHelper != null) {
            mTextHelper.onSetCompoundDrawables();
        }
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getCompoundDrawableTintList(TextView)}
     *
     * @return the tint applied to the compound drawables
     * @attr ref androidx.appcompat.R.styleable#AppCompatTextView_drawableTint
     * @see #setSupportCompoundDrawablesTintList(ColorStateList)
     *
     */
    @Nullable
    @Override
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    public ColorStateList getSupportCompoundDrawablesTintList() {
        return mTextHelper.getCompoundDrawableTintList();
    }

    /**
     * This should be accessed via {@link
     * androidx.core.widget.TextViewCompat#setCompoundDrawableTintList(TextView, ColorStateList)}
     *
     * Applies a tint to the compound drawables. Does not modify the current tint mode, which is
     * {@link PorterDuff.Mode#SRC_IN} by default.
     * <p>
     * Subsequent calls to {@link #setCompoundDrawables(Drawable, Drawable, Drawable, Drawable)} and
     * related methods will automatically mutate the drawables and apply the specified tint and tint
     * mode using {@link Drawable#setTintList(ColorStateList)}.
     *
     * @param tintList the tint to apply, may be {@code null} to clear tint
     * @attr ref androidx.appcompat.R.styleable#AppCompatTextView_drawableTint
     * @see #getSupportCompoundDrawablesTintList()
     *
     */
    @Override
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    public void setSupportCompoundDrawablesTintList(@Nullable ColorStateList tintList) {
        mTextHelper.setCompoundDrawableTintList(tintList);
        mTextHelper.applyCompoundDrawablesTints();
    }

    /**
     * This should be accessed via
     * {@link androidx.core.widget.TextViewCompat#getCompoundDrawableTintMode(TextView)}
     *
     * Returns the blending mode used to apply the tint to the compound drawables, if specified.
     *
     * @return the blending mode used to apply the tint to the compound drawables
     * @attr ref androidx.appcompat.R.styleable#AppCompatTextView_drawableTintMode
     * @see #setSupportCompoundDrawablesTintMode(PorterDuff.Mode)
     *
     */
    @Nullable
    @Override
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    public PorterDuff.Mode getSupportCompoundDrawablesTintMode() {
        return mTextHelper.getCompoundDrawableTintMode();
    }

    /**
     * This should be accessed via {@link
     * androidx.core.widget.TextViewCompat#setCompoundDrawableTintMode(TextView, PorterDuff.Mode)}
     *
     * Specifies the blending mode used to apply the tint specified by
     * {@link #setSupportCompoundDrawablesTintList(ColorStateList)} to the compound drawables. The
     * default mode is {@link PorterDuff.Mode#SRC_IN}.
     *
     * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
     * @attr ref androidx.appcompat.R.styleable#AppCompatTextView_drawableTintMode
     * @see #setSupportCompoundDrawablesTintList(ColorStateList)
     *
     */
    @Override
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    public void setSupportCompoundDrawablesTintMode(@Nullable PorterDuff.Mode tintMode) {
        mTextHelper.setCompoundDrawableTintMode(tintMode);
        mTextHelper.applyCompoundDrawablesTints();
    }

    @Override
    public void setTypeface(@Nullable Typeface tf, int style) {
        if (mIsSetTypefaceProcessing) {
            // b/151782655
            // Some device up to API19 recursively calls setTypeface. To avoid infinity recursive
            // setTypeface call, exit if we know this is re-entrant call.
            // TODO(nona): Remove this once Android X minSdkVersion moves to API21.
            return;
        }
        Typeface finalTypeface = null;
        if (tf != null && style > 0) {
            finalTypeface = TypefaceCompat.create(getContext(), tf, style);
        }

        mIsSetTypefaceProcessing = true;
        try {
            super.setTypeface(finalTypeface != null ? finalTypeface : tf, style);
        } finally {
            mIsSetTypefaceProcessing = false;
        }

    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (Build.VERSION.SDK_INT >= 30 && Build.VERSION.SDK_INT < 33 && onCheckIsTextEditor()) {
            final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
                    Context.INPUT_METHOD_SERVICE);
            // If the AppCompatTextView is editable, user can input text on it.
            // Calling isActive() here implied a checkFocus() call to update the active served
            // view for input method. This is a backport for mServedView was detached, but the
            // next served view gets mistakenly cleared as well.
            // https://android.googlesource.com/platform/frameworks/base/+/734613a500fb
            imm.isActive(this);
        }
    }

    @UiThread
    @RequiresApi(api = 26)
    SuperCaller getSuperCaller() {
        if (mSuperCaller == null) {
            if (Build.VERSION.SDK_INT >= 34) {
                mSuperCaller = new SuperCallerApi34();
            } else if (Build.VERSION.SDK_INT >= 28) {
                mSuperCaller = new SuperCallerApi28();
            } else if (Build.VERSION.SDK_INT >= 26) {
                mSuperCaller = new SuperCallerApi26();
            }
        }
        return mSuperCaller;
    }



    private interface SuperCaller {
        // api 26
        int getAutoSizeMaxTextSize();
        int getAutoSizeMinTextSize();
        int getAutoSizeStepGranularity();
        int[] getAutoSizeTextAvailableSizes();
        int getAutoSizeTextType();
        TextClassifier getTextClassifier();
        void setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize,
                int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit);
        void setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes, int unit);
        void setAutoSizeTextTypeWithDefaults(int autoSizeTextType);
        void setTextClassifier(@Nullable TextClassifier textClassifier);

        // api 28
        void setFirstBaselineToTopHeight(@Px int firstBaselineToTopHeight);
        void setLastBaselineToBottomHeight(@Px int lastBaselineToBottomHeight);

        // api 34
        void setLineHeight(int unit, @FloatRange(from = 0) float lineHeight);
    }

    @RequiresApi(api = 26)
    class SuperCallerApi26 implements SuperCaller {
        @Override
        public int getAutoSizeMaxTextSize() {
            return AppCompatTextView.super.getAutoSizeMaxTextSize();
        }

        @Override
        public int getAutoSizeMinTextSize() {
            return AppCompatTextView.super.getAutoSizeMinTextSize();
        }

        @Override
        public int getAutoSizeStepGranularity() {
            return AppCompatTextView.super.getAutoSizeStepGranularity();
        }

        @Override
        public int[] getAutoSizeTextAvailableSizes() {
            return AppCompatTextView.super.getAutoSizeTextAvailableSizes();
        }

        @Override
        public int getAutoSizeTextType() {
            return AppCompatTextView.super.getAutoSizeTextType();
        }

        @Override
        public TextClassifier getTextClassifier() {
            return AppCompatTextView.super.getTextClassifier();
        }

        @Override
        public void setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize,
                int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit) {
            AppCompatTextView.super.setAutoSizeTextTypeUniformWithConfiguration(autoSizeMinTextSize,
                    autoSizeMaxTextSize, autoSizeStepGranularity, unit);
        }

        @Override
        public void setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes, int unit) {
            AppCompatTextView.super.setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
        }

        @Override
        public void setAutoSizeTextTypeWithDefaults(int autoSizeTextType) {
            AppCompatTextView.super.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
        }

        @Override
        public void setTextClassifier(@Nullable TextClassifier textClassifier) {
            AppCompatTextView.super.setTextClassifier(textClassifier);
        }

        @Override
        public void setFirstBaselineToTopHeight(int firstBaselineToTopHeight) {}

        @Override
        public void setLastBaselineToBottomHeight(int lastBaselineToBottomHeight) {}

        @Override
        public void setLineHeight(int unit, float lineHeight) {}
    }

    @RequiresApi(api = 28)
    class SuperCallerApi28 extends SuperCallerApi26 {

        @Override
        public void setFirstBaselineToTopHeight(@Px int firstBaselineToTopHeight) {
            AppCompatTextView.super.setFirstBaselineToTopHeight(firstBaselineToTopHeight);
        }

        @Override
        public void setLastBaselineToBottomHeight(@Px int lastBaselineToBottomHeight) {
            AppCompatTextView.super.setLastBaselineToBottomHeight(lastBaselineToBottomHeight);
        }
    }

    @RequiresApi(api = 34)
    class SuperCallerApi34 extends SuperCallerApi28 {
        @Override
        public void setLineHeight(int unit, float lineHeight) {
            AppCompatTextView.super.setLineHeight(unit, lineHeight);
        }
    }
}