/* * Copyright (C) 2014 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 android.support.v7.widget; import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.support.annotation.RestrictTo; import android.support.annotation.StyleableRes; import android.support.v4.content.res.ResourcesCompat; import android.support.v4.os.BuildCompat; import android.support.v7.content.res.AppCompatResources; import android.util.AttributeSet; import android.util.TypedValue; import android.widget.TextView; /** * A class that wraps a {@link android.content.res.TypedArray} and provides the same public API * surface. The purpose of this class is so that we can intercept calls to new APIs. * * @hide */ @RestrictTo(LIBRARY_GROUP) public class TintTypedArray { private final Context mContext; private final TypedArray mWrapped; private TypedValue mTypedValue; public static TintTypedArray obtainStyledAttributes(Context context, AttributeSet set, int[] attrs) { return new TintTypedArray(context, context.obtainStyledAttributes(set, attrs)); } public static TintTypedArray obtainStyledAttributes(Context context, AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { return new TintTypedArray(context, context.obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes)); } public static TintTypedArray obtainStyledAttributes(Context context, int resid, int[] attrs) { return new TintTypedArray(context, context.obtainStyledAttributes(resid, attrs)); } private TintTypedArray(Context context, TypedArray array) { mContext = context; mWrapped = array; } public Drawable getDrawable(int index) { if (mWrapped.hasValue(index)) { final int resourceId = mWrapped.getResourceId(index, 0); if (resourceId != 0) { return AppCompatResources.getDrawable(mContext, resourceId); } } return mWrapped.getDrawable(index); } public Drawable getDrawableIfKnown(int index) { if (mWrapped.hasValue(index)) { final int resourceId = mWrapped.getResourceId(index, 0); if (resourceId != 0) { return AppCompatDrawableManager.get().getDrawable(mContext, resourceId, true); } } return null; } /** * Retrieve the Typeface for the attribute at index. *

* This method will throw an exception if the attribute is defined but is * not a font. * * @param index Index of attribute to retrieve. * @param style A style value used for selecting best match font from the list of family. Note * that this value will be ignored if the platform supports font family(API 24 or later). * @param targetView A text view to be applied this font. If async loading is specified in XML, * this view will be refreshed with result typeface. * * @return Typeface for the attribute, or {@code null} if not defined. * @throws RuntimeException if the TypedArray has already been recycled. * @throws UnsupportedOperationException if the attribute is defined but is * not a font resource. */ @Nullable public Typeface getFont(@StyleableRes int index, int style, @NonNull TextView targetView) { if (BuildCompat.isAtLeastO()) { return mWrapped.getFont(index); } final int resourceId = mWrapped.getResourceId(index, 0); if (resourceId == 0) { return null; } if (mTypedValue == null) { mTypedValue = new TypedValue(); } return ResourcesCompat.getFont(mContext, resourceId, mTypedValue, style, targetView); } public int length() { return mWrapped.length(); } public int getIndexCount() { return mWrapped.getIndexCount(); } public int getIndex(int at) { return mWrapped.getIndex(at); } public Resources getResources() { return mWrapped.getResources(); } public CharSequence getText(int index) { return mWrapped.getText(index); } public String getString(int index) { return mWrapped.getString(index); } public String getNonResourceString(int index) { return mWrapped.getNonResourceString(index); } public boolean getBoolean(int index, boolean defValue) { return mWrapped.getBoolean(index, defValue); } public int getInt(int index, int defValue) { return mWrapped.getInt(index, defValue); } public float getFloat(int index, float defValue) { return mWrapped.getFloat(index, defValue); } public int getColor(int index, int defValue) { return mWrapped.getColor(index, defValue); } public ColorStateList getColorStateList(int index) { if (mWrapped.hasValue(index)) { final int resourceId = mWrapped.getResourceId(index, 0); if (resourceId != 0) { final ColorStateList value = AppCompatResources.getColorStateList(mContext, resourceId); if (value != null) { return value; } } } return mWrapped.getColorStateList(index); } public int getInteger(int index, int defValue) { return mWrapped.getInteger(index, defValue); } public float getDimension(int index, float defValue) { return mWrapped.getDimension(index, defValue); } public int getDimensionPixelOffset(int index, int defValue) { return mWrapped.getDimensionPixelOffset(index, defValue); } public int getDimensionPixelSize(int index, int defValue) { return mWrapped.getDimensionPixelSize(index, defValue); } public int getLayoutDimension(int index, String name) { return mWrapped.getLayoutDimension(index, name); } public int getLayoutDimension(int index, int defValue) { return mWrapped.getLayoutDimension(index, defValue); } public float getFraction(int index, int base, int pbase, float defValue) { return mWrapped.getFraction(index, base, pbase, defValue); } public int getResourceId(int index, int defValue) { return mWrapped.getResourceId(index, defValue); } public CharSequence[] getTextArray(int index) { return mWrapped.getTextArray(index); } public boolean getValue(int index, TypedValue outValue) { return mWrapped.getValue(index, outValue); } public int getType(int index) { if (Build.VERSION.SDK_INT >= 21) { return mWrapped.getType(index); } else { if (mTypedValue == null) { mTypedValue = new TypedValue(); } mWrapped.getValue(index, mTypedValue); return mTypedValue.type; } } public boolean hasValue(int index) { return mWrapped.hasValue(index); } public TypedValue peekValue(int index) { return mWrapped.peekValue(index); } public String getPositionDescription() { return mWrapped.getPositionDescription(); } public void recycle() { mWrapped.recycle(); } @RequiresApi(21) public int getChangingConfigurations() { return mWrapped.getChangingConfigurations(); } }