下面列出了android.graphics.drawable.Drawable#ConstantState() 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private boolean addCachedDrawable(final int key, @NonNull final Drawable drawable) {
if (drawable instanceof FilterableStateListDrawable) {
return false;
}
final Drawable.ConstantState cs = drawable.getConstantState();
if (cs != null) {
synchronized (mDrawableCacheLock) {
if (mCacheDrawables == null) {
mCacheDrawables = new SparseArray<>();
}
mCacheDrawables.put(key, new WeakReference<>(cs));
}
return true;
}
return false;
}
@Nullable
private Drawable getCachedIcon(@NonNull ResourceName name) {
synchronized (sSync) {
final WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+ name + ": " + wr);
if (wr != null) { // we have the activity
final Drawable.ConstantState state = wr.get();
if (state != null) {
if (DEBUG_ICONS) {
Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
}
// Note: It's okay here to not use the newDrawable(Resources) variant
// of the API. The ConstantState comes from a drawable that was
// originally created by passing the proper app Resources instance
// which means the state should already contain the proper
// resources specific information (like density.) See
// BitmapDrawable.BitmapState for instance.
return state.newDrawable();
}
// our entry has been purged
sIconCache.remove(name);
}
}
return null;
}
@Nullable
private Drawable getCachedIcon(@NonNull ResourceName name) {
synchronized (sSync) {
final WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+ name + ": " + wr);
if (wr != null) { // we have the activity
final Drawable.ConstantState state = wr.get();
if (state != null) {
if (DEBUG_ICONS) {
Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
}
// Note: It's okay here to not use the newDrawable(Resources) variant
// of the API. The ConstantState comes from a drawable that was
// originally created by passing the proper app Resources instance
// which means the state should already contain the proper
// resources specific information (like density.) See
// BitmapDrawable.BitmapState for instance.
return state.newDrawable();
}
// our entry has been purged
sIconCache.remove(name);
}
}
return null;
}
private Drawable.ConstantState updateButtonWithIconFromExternalActivity(
int buttonId, ComponentName activityName, int fallbackDrawableId,
String toolbarResourceName) {
ImageView button = (ImageView) findViewById(buttonId);
Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName,
toolbarResourceName);
if (button != null) {
// If we were unable to find the icon via the meta-data, use a
// generic one
if (toolbarIcon == null) {
button.setImageResource(fallbackDrawableId);
} else {
button.setImageDrawable(toolbarIcon);
}
}
return toolbarIcon != null ? toolbarIcon.getConstantState() : null;
}
@Nullable
private Drawable getCachedIcon(@NonNull ResourceName name) {
synchronized (sSync) {
final WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+ name + ": " + wr);
if (wr != null) { // we have the activity
final Drawable.ConstantState state = wr.get();
if (state != null) {
if (DEBUG_ICONS) {
Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
}
// Note: It's okay here to not use the newDrawable(Resources) variant
// of the API. The ConstantState comes from a drawable that was
// originally created by passing the proper app Resources instance
// which means the state should already contain the proper
// resources specific information (like density.) See
// BitmapDrawable.BitmapState for instance.
return state.newDrawable();
}
// our entry has been purged
sIconCache.remove(name);
}
}
return null;
}
private static boolean shouldMutateBackground(Drawable drawable) {
if (Build.VERSION.SDK_INT >= 16) {
// For SDK 16+, we should be fine mutating the drawable
return true;
}
if (drawable instanceof LayerDrawable) {
return Build.VERSION.SDK_INT >= 16;
} else if (drawable instanceof InsetDrawable) {
return Build.VERSION.SDK_INT >= 14;
} else if (drawable instanceof DrawableContainer) {
// If we have a DrawableContainer, let's traverse it's child array
final Drawable.ConstantState state = drawable.getConstantState();
if (state instanceof DrawableContainer.DrawableContainerState) {
final DrawableContainer.DrawableContainerState containerState =
(DrawableContainer.DrawableContainerState) state;
for (Drawable child : containerState.getChildren()) {
if (!shouldMutateBackground(child)) {
return false;
}
}
}
}
return true;
}
/**
* Gets the activity or application icon for an activity.
* Uses the local icon cache for fast repeated lookups.
*
* @param component Name of an activity.
* @return A drawable, or {@code null} if neither the activity nor the application
* has an icon set.
*/
private Drawable getActivityIconWithCache(ComponentName component) {
// First check the icon cache
String componentIconKey = component.flattenToShortString();
// Using containsKey() since we also store null values.
if (mOutsideDrawablesCache.containsKey(componentIconKey)) {
Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey);
return cached == null ? null : cached.newDrawable(mProviderContext.getResources());
}
// Then try the activity or application icon
Drawable drawable = getActivityIcon(component);
// Stick it in the cache so we don't do this lookup again.
Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState();
mOutsideDrawablesCache.put(componentIconKey, toCache);
return drawable;
}
private static Drawable getNewIf(Drawable d, Resources res) {
if (d==null) return res.getDrawable(R.mipmap.launcher).mutate();
Drawable.ConstantState cd = d.getConstantState();
if (cd!=null) {
d = cd.newDrawable(res);
} else {
d.mutate();
}
return d;
}
/**
* 设置子项图片
*
* @param item 子项图片
*/
public void setDrawable(Drawable item) {
if (item == null)
item = getDefaultDrawable(Color.TRANSPARENT);
final Drawable.ConstantState state = item.getConstantState();
final Drawable normal = item;
final Drawable selected;
if (state != null) {
selected = state.newDrawable(getResources()).mutate();
selected.setState(SELECTED_STATE_SET);
} else {
selected = item;
}
setDrawables(normal, selected);
}
private Drawable checkIconCache(String resourceUri) {
Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri);
if (cached == null) {
return null;
}
if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri);
return cached.newDrawable();
}
private static void cacheDrawable(TypedValue value, Resources resources, Resources.Theme theme, boolean isColorDrawable, long key, Drawable drawable, LongSparseArray<WeakReference<Drawable.ConstantState>> caches) {
Drawable.ConstantState cs = drawable.getConstantState();
if (cs == null) {
return;
}
synchronized (mAccessLock) {
caches.put(key, new WeakReference<>(cs));
}
}
@Override
public void setIcon(Drawable icon) {
if (icon != null) {
Drawable.ConstantState state = icon.getConstantState();
icon = DrawableCompat.wrap(state == null ? icon : state.newDrawable()).mutate();
DrawableCompat.setTintList(icon, mIconTint);
}
mIcon.setImageDrawable(icon);
}
private static Drawable getCachedDrawable(LongSparseArray<WeakReference<Drawable.ConstantState>> cache,
long key, Resources res) {
synchronized (mAccessLock) {
WeakReference<Drawable.ConstantState> wr = cache.get(key);
if (wr != null) {
Drawable.ConstantState entry = wr.get();
if (entry != null) {
return entry.newDrawable(res);
} else {
cache.delete(key);
}
}
}
return null;
}
/**
* Some drawable implementations have problems with mutation. This method returns false if
* there is a known issue in the given drawable's implementation.
*/
public static boolean canSafelyMutateDrawable(@NonNull Drawable drawable) {
if (Build.VERSION.SDK_INT < 15 && drawable instanceof InsetDrawable) {
return false;
} else if (Build.VERSION.SDK_INT < 15 && drawable instanceof GradientDrawable) {
// GradientDrawable has a bug pre-ICS which results in mutate() resulting
// in loss of color
return false;
} else if (Build.VERSION.SDK_INT < 17 && drawable instanceof LayerDrawable) {
return false;
}
if (drawable instanceof DrawableContainer) {
// If we have a DrawableContainer, let's traverse it's child array
final Drawable.ConstantState state = drawable.getConstantState();
if (state instanceof DrawableContainer.DrawableContainerState) {
final DrawableContainer.DrawableContainerState containerState =
(DrawableContainer.DrawableContainerState) state;
for (final Drawable child : containerState.getChildren()) {
if (!canSafelyMutateDrawable(child)) {
return false;
}
}
}
} else if (SkinCompatVersionUtils.isV4DrawableWrapper(drawable)) {
return canSafelyMutateDrawable(SkinCompatVersionUtils.getV4DrawableWrapperWrappedDrawable(drawable));
} else if (SkinCompatVersionUtils.isV4WrappedDrawable(drawable)) {
return canSafelyMutateDrawable(SkinCompatVersionUtils.getV4WrappedDrawableWrappedDrawable(drawable));
} else if (SkinCompatVersionUtils.isV7DrawableWrapper(drawable)) {
return canSafelyMutateDrawable(SkinCompatVersionUtils.getV7DrawableWrapperWrappedDrawable(drawable));
} else if (drawable instanceof ScaleDrawable) {
Drawable scaleDrawable = ((ScaleDrawable) drawable).getDrawable();
if (scaleDrawable != null) {
return canSafelyMutateDrawable(scaleDrawable);
}
}
return true;
}
private Drawable checkIconCache(String resourceUri) {
Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri);
if (cached == null) {
return null;
}
if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri);
return cached.newDrawable();
}
private Drawable checkIconCache(String resourceUri) {
Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri);
if (cached == null) {
return null;
}
if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri);
return cached.newDrawable();
}
private LayerDrawable newDrawableFromConstantState(Drawable.ConstantState constantState)
{
return (LayerDrawable) constantState.newDrawable(getContext().getResources());
}
LongSparseArray<Drawable.ConstantState> getPreloadedDrawables() {
return sPreloadedDrawables[0];
}
public SuggestionsAdapter(Context context, SearchView searchView, SearchableInfo searchable,
WeakHashMap<String, Drawable.ConstantState> outsideDrawablesCache) {
super(context, searchView.getSuggestionRowLayout(), null /* no initial cursor */,
true /* auto-requery */);
mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
mSearchView = searchView;
mSearchable = searchable;
mCommitIconResId = searchView.getSuggestionCommitIconResId();
// set up provider resources (gives us icons, etc.)
final Context activityContext = mSearchable.getActivityContext(mContext);
mProviderContext = mSearchable.getProviderContext(mContext, activityContext);
mOutsideDrawablesCache = outsideDrawablesCache;
// mStartSpinnerRunnable = new Runnable() {
// public void run() {
// // mSearchView.setWorking(true); // TODO:
// }
// };
//
// mStopSpinnerRunnable = new Runnable() {
// public void run() {
// // mSearchView.setWorking(false); // TODO:
// }
// };
// delay 500ms when deleting
getFilter().setDelayer(new Filter.Delayer() {
private int mPreviousLength = 0;
public long getPostingDelay(CharSequence constraint) {
if (constraint == null) return 0;
long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0;
mPreviousLength = constraint.length();
return delay;
}
});
}
/**
* If the resource is cached, creates and returns a new instance of it.
*
* @param key a key that uniquely identifies the drawable resource
* @param resources a Resources object from which to create new instances.
* @param theme the theme where the resource will be used
* @return a new instance of the resource, or {@code null} if not in
* the cache
*/
public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
final Drawable.ConstantState entry = get(key, theme);
if (entry != null) {
return entry.newDrawable(resources, theme);
}
return null;
}