AdaptiveIconDrawable.java revision 547010ff863e634186fddf75890b6894f1cfa6be
136e612a488511940b61f09803b270aa1c61b68e0Jason Sams/* 2dd6c8b34f172ba699954e4d3095dba8c0fd5e930Jason Sams * Copyright (C) 2017 The Android Open Source Project 336e612a488511940b61f09803b270aa1c61b68e0Jason Sams * 436e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 536e612a488511940b61f09803b270aa1c61b68e0Jason Sams * you may not use this file except in compliance with the License. 636e612a488511940b61f09803b270aa1c61b68e0Jason Sams * You may obtain a copy of the License at 736e612a488511940b61f09803b270aa1c61b68e0Jason Sams * 836e612a488511940b61f09803b270aa1c61b68e0Jason Sams * http://www.apache.org/licenses/LICENSE-2.0 936e612a488511940b61f09803b270aa1c61b68e0Jason Sams * 1036e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Unless required by applicable law or agreed to in writing, software 1136e612a488511940b61f09803b270aa1c61b68e0Jason Sams * distributed under the License is distributed on an "AS IS" BASIS, 1236e612a488511940b61f09803b270aa1c61b68e0Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1336e612a488511940b61f09803b270aa1c61b68e0Jason Sams * See the License for the specific language governing permissions and 1436e612a488511940b61f09803b270aa1c61b68e0Jason Sams * limitations under the License. 1536e612a488511940b61f09803b270aa1c61b68e0Jason Sams */ 1636e612a488511940b61f09803b270aa1c61b68e0Jason Sams 1736e612a488511940b61f09803b270aa1c61b68e0Jason Samspackage android.graphics.drawable; 1836e612a488511940b61f09803b270aa1c61b68e0Jason Sams 199c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hinesimport static android.graphics.drawable.Drawable.obtainAttributes; 20c11e25c4e653124def1fb18e203b894f42106cbeTim Murray 21c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.annotation.NonNull; 22c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.annotation.Nullable; 23c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.annotation.TestApi; 24c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.pm.ActivityInfo.Config; 25c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.ColorStateList; 26c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.Resources; 27c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.Resources.Theme; 28c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.content.res.TypedArray; 29c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Bitmap; 30c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.BitmapShader; 31c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Canvas; 32c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.ColorFilter; 33a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Samsimport android.graphics.Matrix; 34c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Outline; 35c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Paint; 36c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Path; 37c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.PixelFormat; 38c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.PorterDuff.Mode; 39c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Rect; 40c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Region; 41c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Shader; 42c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.graphics.Shader.TileMode; 43c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.util.AttributeSet; 44c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.util.DisplayMetrics; 45c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport android.util.PathParser; 463aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez 473aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandezimport com.android.internal.R; 483aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandezimport org.xmlpull.v1.XmlPullParser; 49c11e25c4e653124def1fb18e203b894f42106cbeTim Murrayimport org.xmlpull.v1.XmlPullParserException; 50c11e25c4e653124def1fb18e203b894f42106cbeTim Murray 513aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandezimport java.io.IOException; 5236e612a488511940b61f09803b270aa1c61b68e0Jason Sams 5336e612a488511940b61f09803b270aa1c61b68e0Jason Sams/** 54ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams * This drawable supports two layers: foreground and background. 55718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * 56718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * <p>The layers are clipped when rendering using the mask path defined in the device configuration. 5770d4e5024298f71edb3b04867e05568f5495b4ceJason Sams * 587d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk * <p>This class can also be created via XML inflation using <code><adaptive-icon></code> tag 59ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams * in addition to dynamic creation. 603aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk */ 613aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchoukpublic class AdaptiveIconDrawable extends Drawable implements Drawable.Callback { 62718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams 63718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams /** 64718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * Mask path is defined inside device configuration in following dimension: [100 x 100] 65718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * @hide 66718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams */ 673aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk public static final float MASK_SIZE = 100f; 683aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk private static final float SAFEZONE_SCALE = .9f; 693aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk 703aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk /** 713aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * All four sides of the layers are padded with extra inset so as to provide 723aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * extra content to reveal within the clip path when performing affine transformations on the 733aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * layers. 743aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * 753aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * Each layers will reserve 25% of it's width and height. 763aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * 773aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * As a result, the view port of the layers is smaller than their intrinsic width and height. 783aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk */ 793aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk private static final float EXTRA_INSET_PERCENTAGE = 1 / 4f; 803aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk private static final float DEFAULT_VIEW_PORT_SCALE = 1f / (1 + 2 * EXTRA_INSET_PERCENTAGE); 813aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk 823aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk /** 833aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * Clip path defined in {@link com.android.internal.R.string.config_icon_mask}. 843aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk */ 853aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk private static Path sMask; 863aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk 873aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk /** 883aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * Scaled mask based on the view bounds. 893aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk */ 909c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines private final Path mMask; 917d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk private final Matrix mMaskMatrix; 927d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk private final Region mTransparentRegion; 93918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk 94718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams private Bitmap mMaskBitmap; 959c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines 96918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk /** 97918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk * Indices used to access {@link #mLayerState.mChildDrawable} array for foreground and 98fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk * background layer. 99fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk */ 100fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk private static final int BACKGROUND_ID = 0; 101fd79e02e0fec8620da7affaadcf275cf0518241aAlex Sakhartchouk private static final int FOREGROUND_ID = 1; 102a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams 1039c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines /** 104a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams * State variable that maintains the {@link ChildDrawable} array. 105f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk */ 106f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk LayerState mLayerState; 107f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk 108f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk private Shader mLayersShader; 109f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk private Bitmap mLayersBitmap; 110f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk 111f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk private final Rect mTmpOutRect = new Rect(); 112f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk private Rect mHotspotBounds; 113a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams private boolean mMutated; 114a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams 115a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams private boolean mSuspendChildInvalidation; 116a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams private boolean mChildRequestedInvalidation; 117fb4f5cf614091f7876c6a895ad81f00b7837cd03Jason Sams private final Canvas mCanvas; 118fb4f5cf614091f7876c6a895ad81f00b7837cd03Jason Sams private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | 119a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams Paint.FILTER_BITMAP_FLAG); 120718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams 1213aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk /** 122a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams * Constructor used for xml inflation. 123718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams */ 12402f41705199336f808ece50d81585450e7f8f61fStephen Hines AdaptiveIconDrawable() { 125718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams this((LayerState) null, null); 126718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams } 127718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams 128ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines /** 129718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * The one constructor to rule them all. This is called by all public 130718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * constructors to set the state and initialize local properties. 131718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams */ 13252d836332f6aae74ed97fda1b53681f36710af64Stephen Hines AdaptiveIconDrawable(@Nullable LayerState state, @Nullable Resources res) { 133718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams mLayerState = createConstantState(state, res); 134f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams 135f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams if (sMask == null) { 136f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams sMask = PathParser.createPathFromPathData( 137f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask)); 138f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams } 139f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams mMask = new Path(); 1401d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams mMaskMatrix = new Matrix(); 1411d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams mCanvas = new Canvas(); 1421d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams mTransparentRegion = new Region(); 1431d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams } 144b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams 145b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams private ChildDrawable createChildDrawable(Drawable drawable) { 146b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams final ChildDrawable layer = new ChildDrawable(mLayerState.mDensity); 147b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams layer.mDrawable = drawable; 148b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams layer.mDrawable.setCallback(this); 149b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams mLayerState.mChildrenChangingConfigurations |= 150b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams layer.mDrawable.getChangingConfigurations(); 151b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams return layer; 152b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams } 153b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams 154b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams LayerState createConstantState(@Nullable LayerState state, @Nullable Resources res) { 155718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams return new LayerState(state, this, res); 156718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams } 157718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams 158718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams /** 159718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * Constructor used to dynamically create this drawable. 160718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * 161718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * @param backgroundDrawable drawable that should be rendered in the background 162b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams * @param foregroundDrawable drawable that should be rendered in the foreground 163b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams * @hide 164b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams */ 165b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams public AdaptiveIconDrawable(Drawable backgroundDrawable, 166b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams Drawable foregroundDrawable) { 167b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams this((LayerState)null, null); 168b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams if (backgroundDrawable != null) { 169b49dfeaea96375b3b8fc1921f8b891c340f0baf2Jason Sams addLayer(BACKGROUND_ID, createChildDrawable(backgroundDrawable)); 170768bc02d815a94ad29146f1ed60c847d1af118ccJason Sams } 171768bc02d815a94ad29146f1ed60c847d1af118ccJason Sams if (foregroundDrawable != null) { 1729c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines addLayer(FOREGROUND_ID, createChildDrawable(foregroundDrawable)); 173a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams } 174a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams } 175a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams 176a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams /** 177a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams * Sets the layer to the {@param index} and invalidates cache. 178718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * 179718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * @param index The index of the layer. 180718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams * @param layer The layer to add. 181718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams */ 182718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams private void addLayer(int index, @NonNull ChildDrawable layer) { 183718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams mLayerState.mChildren[index] = layer; 184718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams mLayerState.invalidateCache(); 1858e90f2bc1fa35a2dc7bd2aab8b8241b628800218Alex Sakhartchouk } 1868140d7b0f62a6e5b54e318c959f2d501f7ee6784Jason Sams 1878140d7b0f62a6e5b54e318c959f2d501f7ee6784Jason Sams @Override 188718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, 189718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams @NonNull AttributeSet attrs, @Nullable Theme theme) 190718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams throws XmlPullParserException, IOException { 191718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams super.inflate(r, parser, attrs, theme); 192ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams 19336e612a488511940b61f09803b270aa1c61b68e0Jason Sams final LayerState state = mLayerState; 19436e612a488511940b61f09803b270aa1c61b68e0Jason Sams if (state == null) { 1959c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines return; 196a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams } 197a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams 198a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams // The density may have changed since the last update. This will 199a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams // apply scaling to any existing constant state properties. 200a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams final int density = Drawable.resolveDensity(r, 0); 201c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams state.setDensity(density); 202c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams 203c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams final ChildDrawable[] array = state.mChildren; 204c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams for (int i = 0; i < state.mChildren.length; i++) { 205c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams final ChildDrawable layer = array[i]; 206c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams layer.setDensity(density); 207c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams } 208c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams inflateLayers(r, parser, attrs, theme); 209c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams } 210c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams 211c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams /** 212c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams * All four sides of the layers are padded with extra inset so as to provide 2139c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines * extra content to reveal within the clip path when performing affine transformations on the 214918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk * layers. 215918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk */ 216918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk public static float getExtraInsetPercentage() { 217918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk return EXTRA_INSET_PERCENTAGE; 2187d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2197d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk 2207d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk /** 2213aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * Only call this method after bound is set on this drawable. 2227d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk * 2237d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk * @return the mask path object used to clip the drawable 2243aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk */ 2257d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk public Path getIconMask() { 2267d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk return mMask; 2279c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines } 228918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk 229918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk /** 2307d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk * @return the foreground drawable managed by this drawable 2317d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk */ 2327d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk public Drawable getForeground() { 2337d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk return mLayerState.mChildren[FOREGROUND_ID].mDrawable; 2343aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk } 2357d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk 2367d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk /** 2373aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk * @return the background drawable managed by this drawable 2387d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk */ 2397d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk public Drawable getBackground() { 2403aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk return mLayerState.mChildren[BACKGROUND_ID].mDrawable; 2417d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2427d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk 2439c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines @Override 244918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk protected void onBoundsChange(Rect bounds) { 245918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk if (bounds.isEmpty()) { 2467d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk return; 2477d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2487d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk updateLayerBounds(bounds); 2497d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2503aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk 2517d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk private void updateLayerBounds(Rect bounds) { 2527d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk try { 2533aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk suspendChildInvalidation(); 2547d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk updateLayerBoundsInternal(bounds); 2557d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk updateMaskBoundsInternal(bounds); 2563aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk } finally { 2577d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk resumeChildInvalidation(); 2587d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2599c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines } 260918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk 261918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk /** 262918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk * Set the child layer bounds bigger than the view port size by {@link #DEFAULT_VIEW_PORT_SCALE} 2637d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk */ 2647d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk private void updateLayerBoundsInternal(Rect bounds) { 2657d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk int cX = bounds.width() / 2; 2667d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk int cY = bounds.height() / 2; 2673aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk 2687d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk for (int i = 0, count = mLayerState.N_CHILDREN; i < count; i++) { 2697d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk final ChildDrawable r = mLayerState.mChildren[i]; 2703aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk if (r == null) { 2717d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk continue; 2727d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2733aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk final Drawable d = r.mDrawable; 2747d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk if (d == null) { 2757d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk continue; 2769c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines } 277918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk 278918e840628a0b40a95fd42618f604ea5a44aebaeAlex Sakhartchouk int insetWidth = (int) (bounds.width() / (DEFAULT_VIEW_PORT_SCALE * 2)); 2797d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk int insetHeight = (int) (bounds.height() / (DEFAULT_VIEW_PORT_SCALE * 2)); 2807d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk final Rect outRect = mTmpOutRect; 2817d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk outRect.set(cX - insetWidth, cY - insetHeight, cX + insetWidth, cY + insetHeight); 2827d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk 2833aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk d.setBounds(outRect); 2847d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2857d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk } 2863aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk 2877d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk private void updateMaskBoundsInternal(Rect b) { 2887d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk mMaskMatrix.setScale(b.width() / MASK_SIZE, b.height() / MASK_SIZE); 2893aac0abe7965ce9e2078c7d5796805d83e39df7cAlex Sakhartchouk sMask.transform(mMaskMatrix, mMask); 2907d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk 2917d5f5e7c8943e043a422ad51c85d4e1684c37e28Alex Sakhartchouk if (mMaskBitmap == null || mMaskBitmap.getWidth() != b.width() || 2929c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines mMaskBitmap.getHeight() != b.height()) { 293f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8); 294f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888); 295f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk } 296f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mCanvas.setBitmap(mMaskBitmap); 297f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mPaint.setShader(null); 298f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mCanvas.drawPath(mMask, mPaint); 2999c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines 300f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk // reset everything that depends on the view bounds 301f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mTransparentRegion.setEmpty(); 302f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk mLayersShader = null; 303f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk } 304f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk 305f5d8ac7cc35747ef7285ccc196f616b96229def9Alex Sakhartchouk @Override 3069c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines public void draw(Canvas canvas) { 307a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams if (mLayersShader == null) { 308a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams mCanvas.setBitmap(mLayersBitmap); 309a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 310a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams if (mLayerState.mChildren[i] == null) { 311a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams continue; 312a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams } 313f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams final Drawable dr = mLayerState.mChildren[i].mDrawable; 3146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 3156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni dr.draw(mCanvas); 3166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 3176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 3186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mLayersShader = new BitmapShader(mLayersBitmap, TileMode.CLAMP, TileMode.CLAMP); 3196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mPaint.setShader(mLayersShader); 320f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams } 321f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams if (mMaskBitmap != null) { 322f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams Rect bounds = getBounds(); 323f110d4b787b91dabe968a812e76e5c1f8d953487Jason Sams canvas.drawBitmap(mMaskBitmap, bounds.left, bounds.top, mPaint); 3249c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines } 325a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams } 326a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams 327a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams @Override 328a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams public void invalidateSelf() { 329a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams mLayersShader = null; 330a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams super.invalidateSelf(); 3318cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 3326bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3336bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 3346bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void getOutline(@NonNull Outline outline) { 3356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni outline.setConvexPath(mMask); 3366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 3376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3383c0dfbab807a459622aeade4940daddf482dec66Jason Sams /** @hide */ 3398cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams @TestApi 3403c0dfbab807a459622aeade4940daddf482dec66Jason Sams public Region getSafeZone() { 341ea84a7c51790f9ba5f2194a66d6cf4ea8d879776Jason Sams mMaskMatrix.reset(); 3429c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines mMaskMatrix.setScale(SAFEZONE_SCALE, SAFEZONE_SCALE, getBounds().centerX(), getBounds().centerY()); 343a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams Path p = new Path(); 344a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams mMask.transform(mMaskMatrix, p); 345a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams Region safezoneRegion = new Region(getBounds()); 346a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams safezoneRegion.setPath(p, safezoneRegion); 347a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams return safezoneRegion; 348a1b13ed0912a7e08f9848196b4ca64dcb5db9d0bJason Sams } 3498cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams 3506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 3516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public @Nullable Region getTransparentRegion() { 3526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (mTransparentRegion.isEmpty()) { 3536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mMask.toggleInverseFillType(); 3546bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mTransparentRegion.set(getBounds()); 3556bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mTransparentRegion.setPath(mMask, mTransparentRegion); 3563c0dfbab807a459622aeade4940daddf482dec66Jason Sams mMask.toggleInverseFillType(); 3578cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 3583c0dfbab807a459622aeade4940daddf482dec66Jason Sams return mTransparentRegion; 3593c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 360e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams 3616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 3626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void applyTheme(@NonNull Theme t) { 3636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni super.applyTheme(t); 3646bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3656bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final LayerState state = mLayerState; 3666bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (state == null) { 367e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams return; 368e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams } 369e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams 370e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams final int density = Drawable.resolveDensity(t.getResources(), 0); 371e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams state.setDensity(density); 3726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = state.mChildren; 3746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < state.N_CHILDREN; i++) { 3756bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable layer = array[i]; 3766bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni layer.setDensity(density); 3776bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 378e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams if (layer.mThemeAttrs != null) { 379e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams final TypedArray a = t.resolveAttributes( 380e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams layer.mThemeAttrs, R.styleable.AdaptiveIconDrawableLayer); 381e29f3e74f71ea730519ff8ae1d8dd4c1630bbaf9Jason Sams updateLayerFromTypedArray(layer, a); 3828cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams a.recycle(); 3836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 3846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable d = layer.mDrawable; 3866bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (d != null && d.canApplyTheme()) { 3876bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni d.applyTheme(t); 3886bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3893c0dfbab807a459622aeade4940daddf482dec66Jason Sams // Update cached mask of child changing configurations. 3908cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams state.mChildrenChangingConfigurations |= d.getChangingConfigurations(); 3913c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 3923c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 3938cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 3946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 3956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni /** 3966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * Inflates child layers using the specified parser. 3976bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni */ 3986bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser, 3996bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @NonNull AttributeSet attrs, @Nullable Theme theme) 4003c0dfbab807a459622aeade4940daddf482dec66Jason Sams throws XmlPullParserException, IOException { 4018cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams final LayerState state = mLayerState; 4023c0dfbab807a459622aeade4940daddf482dec66Jason Sams 4033c0dfbab807a459622aeade4940daddf482dec66Jason Sams final int innerDepth = parser.getDepth() + 1; 40452d836332f6aae74ed97fda1b53681f36710af64Stephen Hines int type; 4056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni int depth; 4066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni int childIndex = 0; 4076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 4086bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { 4096bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (type != XmlPullParser.START_TAG) { 4106bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni continue; 41152d836332f6aae74ed97fda1b53681f36710af64Stephen Hines } 41252d836332f6aae74ed97fda1b53681f36710af64Stephen Hines 41352d836332f6aae74ed97fda1b53681f36710af64Stephen Hines if (depth > innerDepth) { 41452d836332f6aae74ed97fda1b53681f36710af64Stephen Hines continue; 415ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines } 4166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni String tagName = parser.getName(); 4176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (tagName.equals("background")) { 4186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni childIndex = BACKGROUND_ID; 4196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } else if (tagName.equals("foreground")) { 4206bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni childIndex = FOREGROUND_ID; 4216bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } else { 422ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines continue; 423ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines } 424ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines 425ef1dac28d3bf98bd61cd9874fb3ccab42105e9b6Stephen Hines final ChildDrawable layer = new ChildDrawable(state.mDensity); 426a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams final TypedArray a = obtainAttributes(r, theme, attrs, 4276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni R.styleable.AdaptiveIconDrawableLayer); 4286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni updateLayerFromTypedArray(layer, a); 4296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni a.recycle(); 4306bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4316bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni // If the layer doesn't have a drawable or unresolved theme 4326bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni // attribute for a drawable, attempt to parse one from the child 433a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams // element. If multiple child elements exist, we'll only use the 434a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams // first one. 435a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams if (layer.mDrawable == null && (layer.mThemeAttrs == null)) { 436a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams while ((type = parser.next()) == XmlPullParser.TEXT) { 4378cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 4386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (type != XmlPullParser.START_TAG) { 4396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni throw new XmlPullParserException(parser.getPositionDescription() 4406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni + ": <foreground> or <background> tag requires a 'drawable'" 4416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni + "attribute or child tag defining a drawable"); 4426bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4436bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4443c0dfbab807a459622aeade4940daddf482dec66Jason Sams // We found a child drawable. Take ownership. 4458cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme); 4463c0dfbab807a459622aeade4940daddf482dec66Jason Sams layer.mDrawable.setCallback(this); 4473c0dfbab807a459622aeade4940daddf482dec66Jason Sams state.mChildrenChangingConfigurations |= 44802f41705199336f808ece50d81585450e7f8f61fStephen Hines layer.mDrawable.getChangingConfigurations(); 4496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni addLayer(childIndex, layer); 4516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4546bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private void updateLayerFromTypedArray(@NonNull ChildDrawable layer, @NonNull TypedArray a) { 45502f41705199336f808ece50d81585450e7f8f61fStephen Hines final LayerState state = mLayerState; 45602f41705199336f808ece50d81585450e7f8f61fStephen Hines 45702f41705199336f808ece50d81585450e7f8f61fStephen Hines // Account for any configuration changes. 45802f41705199336f808ece50d81585450e7f8f61fStephen Hines state.mChildrenChangingConfigurations |= a.getChangingConfigurations(); 4598cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams 4606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni // Extract the theme attributes, if any. 4616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni layer.mThemeAttrs = a.extractThemeAttrs(); 4626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni Drawable dr = a.getDrawable(R.styleable.AdaptiveIconDrawableLayer_drawable); 4646bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 4656bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (layer.mDrawable != null) { 466a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams // It's possible that a drawable was already set, in which case 4678cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams // we should clear the callback. We may have also integrated the 468a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams // drawable's changing configurations, but we don't have enough 469a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams // information to revert that change. 4708cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams layer.mDrawable.setCallback(null); 4716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni // Take ownership of the new drawable. 4746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni layer.mDrawable = dr; 4756bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni layer.mDrawable.setCallback(this); 4766bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni state.mChildrenChangingConfigurations |= 477a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams layer.mDrawable.getChangingConfigurations(); 4788cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 479a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } 480a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams 4818cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams @Override 4826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public boolean canApplyTheme() { 4836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme(); 4846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4866bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni /** 4876bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * @hide 488a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams */ 4898cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams @Override 490a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams public boolean isProjected() { 491a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams if (super.isProjected()) { 4928cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams return true; 4936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 4946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 4956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] layers = mLayerState.mChildren; 4966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 4976bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (layers[i].mDrawable.isProjected()) { 4986bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return true; 499a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } 5008cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 501a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams return false; 502a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } 5038cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams 5046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni /** 5056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * Temporarily suspends child invalidation. 5066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * 5076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * @see #resumeChildInvalidation() 5086bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni */ 5096bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private void suspendChildInvalidation() { 510a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams mSuspendChildInvalidation = true; 5118cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 512a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams 513a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams /** 5148cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams * Resumes child invalidation after suspension, immediately performing an 5156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * invalidation if one was requested by a child during suspension. 5166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * 5176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni * @see #suspendChildInvalidation() 5186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni */ 5196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private void resumeChildInvalidation() { 5206bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mSuspendChildInvalidation = false; 521a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams 5228cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams if (mChildRequestedInvalidation) { 523a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams mChildRequestedInvalidation = false; 524a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams invalidateSelf(); 5258cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 5266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 5286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 5296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void invalidateDrawable(@NonNull Drawable who) { 5306bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (mSuspendChildInvalidation) { 5316bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mChildRequestedInvalidation = true; 532a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } else { 5338cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams invalidateSelf(); 534a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } 535a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } 5368cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams 5376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 5386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { 5396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni scheduleSelf(what, when); 5406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 5426bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 543a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { 5448cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams unscheduleSelf(what); 545a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams } 546a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams 5478cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams @Override 5486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public @Config int getChangingConfigurations() { 5496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return super.getChangingConfigurations() | mLayerState.getChangingConfigurations(); 5506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 5526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 5536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setHotspot(float x, float y) { 554a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams final ChildDrawable[] array = mLayerState.mChildren; 5558cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 556a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams final Drawable dr = array[i].mDrawable; 557a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams if (dr != null) { 5588cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams dr.setHotspot(x, y); 5596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 5636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 5646bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setHotspotBounds(int left, int top, int right, int bottom) { 565a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams final ChildDrawable[] array = mLayerState.mChildren; 5668cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 567a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams final Drawable dr = array[i].mDrawable; 568a70f416c9cf2fc6cc5e132c1d656ce07441d6b82Jason Sams if (dr != null) { 5693a2914132146f340511425d7f78540098606b512Stephen Hines dr.setHotspotBounds(left, top, right, bottom); 5706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 5736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (mHotspotBounds == null) { 5746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mHotspotBounds = new Rect(left, top, right, bottom); 5756bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } else { 5763a2914132146f340511425d7f78540098606b512Stephen Hines mHotspotBounds.set(left, top, right, bottom); 5773a2914132146f340511425d7f78540098606b512Stephen Hines } 5783a2914132146f340511425d7f78540098606b512Stephen Hines } 5793a2914132146f340511425d7f78540098606b512Stephen Hines 5803c0dfbab807a459622aeade4940daddf482dec66Jason Sams @Override 5816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void getHotspotBounds(Rect outRect) { 5826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (mHotspotBounds != null) { 5836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni outRect.set(mHotspotBounds); 5846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } else { 5856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni super.getHotspotBounds(outRect); 5866bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 5873c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 5883c0dfbab807a459622aeade4940daddf482dec66Jason Sams 5893c0dfbab807a459622aeade4940daddf482dec66Jason Sams @Override 5903c0dfbab807a459622aeade4940daddf482dec66Jason Sams public boolean setVisible(boolean visible, boolean restart) { 5913c0dfbab807a459622aeade4940daddf482dec66Jason Sams final boolean changed = super.setVisible(visible, restart); 5926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 5936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 5946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 5956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 5966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 5976bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni dr.setVisible(visible, restart); 5983c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 5993c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6003c0dfbab807a459622aeade4940daddf482dec66Jason Sams 6013c0dfbab807a459622aeade4940daddf482dec66Jason Sams return changed; 6023c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setDither(boolean dither) { 6066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 6076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 6086bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 6093c0dfbab807a459622aeade4940daddf482dec66Jason Sams if (dr != null) { 6103c0dfbab807a459622aeade4940daddf482dec66Jason Sams dr.setDither(dither); 6113c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6123c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6133c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setAlpha(int alpha) { 6176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 6186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 6196bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 6203c0dfbab807a459622aeade4940daddf482dec66Jason Sams if (dr != null) { 6213c0dfbab807a459622aeade4940daddf482dec66Jason Sams dr.setAlpha(alpha); 6223c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6233c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6243c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public int getAlpha() { 6286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = getFirstNonNullDrawable(); 6296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 6306bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return dr.getAlpha(); 6313c0dfbab807a459622aeade4940daddf482dec66Jason Sams } else { 6323c0dfbab807a459622aeade4940daddf482dec66Jason Sams return super.getAlpha(); 6333c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6343c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6353c0dfbab807a459622aeade4940daddf482dec66Jason Sams 6366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setColorFilter(ColorFilter colorFilter) { 6386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 6396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 6406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 6416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 6423c0dfbab807a459622aeade4940daddf482dec66Jason Sams dr.setColorFilter(colorFilter); 6433c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6443c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 6453c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 646a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams 6476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setTintList(ColorStateList tint) { 6496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 6506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final int N = mLayerState.N_CHILDREN; 6516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < N; i++) { 6526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 653a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams if (dr != null) { 654a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams dr.setTintList(tint); 655a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 656a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 657a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 6586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setTintMode(Mode tintMode) { 6616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 6626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final int N = mLayerState.N_CHILDREN; 6636bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < N; i++) { 664a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams final Drawable dr = array[i].mDrawable; 665a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams if (dr != null) { 666a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams dr.setTintMode(tintMode); 667a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 668a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 6696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 6706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private Drawable getFirstNonNullDrawable() { 6726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 6736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 6746bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 675a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams if (dr != null) { 676a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams return dr; 677a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 678a5835a2e5fdb98fdf03a223ddf7e082ba1020807Jason Sams } 6798cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams return null; 6806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 6816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setOpacity(int opacity) { 6836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mLayerState.mOpacityOverride = opacity; 6846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 6856bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6863c0dfbab807a459622aeade4940daddf482dec66Jason Sams @Override 6878cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams public int getOpacity() { 6883c0dfbab807a459622aeade4940daddf482dec66Jason Sams if (mLayerState.mOpacityOverride != PixelFormat.UNKNOWN) { 6893c0dfbab807a459622aeade4940daddf482dec66Jason Sams return mLayerState.mOpacityOverride; 6908cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams } 6916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return mLayerState.getOpacity(); 6926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 6936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 6946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 6956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void setAutoMirrored(boolean mirrored) { 6966bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mLayerState.mAutoMirrored = mirrored; 6973c0dfbab807a459622aeade4940daddf482dec66Jason Sams 6988cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams final ChildDrawable[] array = mLayerState.mChildren; 69936e612a488511940b61f09803b270aa1c61b68e0Jason Sams for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 70036e612a488511940b61f09803b270aa1c61b68e0Jason Sams final Drawable dr = array[i].mDrawable; 7018cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams if (dr != null) { 7026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni dr.setAutoMirrored(mirrored); 7036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7076bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 708718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams public boolean isAutoMirrored() { 7098cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams return mLayerState.mAutoMirrored; 7103c0dfbab807a459622aeade4940daddf482dec66Jason Sams } 71136e612a488511940b61f09803b270aa1c61b68e0Jason Sams 712836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Override 7136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public void jumpToCurrentState() { 7146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 7156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 7166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 7176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 7186bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni dr.jumpToCurrentState(); 719836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 720836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 721836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 722836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 723836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Override 7246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public boolean isStateful() { 7256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return mLayerState.isStateful(); 7266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 7296bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni protected boolean onStateChange(int[] state) { 730836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines boolean changed = false; 731836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 732836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final ChildDrawable[] array = mLayerState.mChildren; 733836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 734836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final Drawable dr = array[i].mDrawable; 7356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null && dr.isStateful() && dr.setState(state)) { 7366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni changed = true; 7376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (changed) { 741836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines updateLayerBounds(getBounds()); 742836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 743836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 744836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return changed; 745836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 7466bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 7486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni protected boolean onLevelChange(int level) { 7496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni boolean changed = false; 7506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 752836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 753836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final Drawable dr = array[i].mDrawable; 754836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (dr != null && dr.setLevel(level)) { 755836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines changed = true; 756836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 7576bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (changed) { 7606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni updateLayerBounds(getBounds()); 7616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7626bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 763836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return changed; 764836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 765836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 766836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Override 7678cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams public int getIntrinsicWidth() { 7686bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return (int)(getMaxIntrinsicWidth() * DEFAULT_VIEW_PORT_SCALE); 7696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private int getMaxIntrinsicWidth() { 7726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni int width = -1; 7736bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 77436e612a488511940b61f09803b270aa1c61b68e0Jason Sams final ChildDrawable r = mLayerState.mChildren[i]; 7758cb39de03aef6097a90033600d11a60ae000a6e4Jason Sams if (r.mDrawable == null) { 77636e612a488511940b61f09803b270aa1c61b68e0Jason Sams continue; 77736e612a488511940b61f09803b270aa1c61b68e0Jason Sams } 778836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final int w = r.mDrawable.getIntrinsicWidth(); 7796bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (w > width) { 7806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni width = w; 7816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 7836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return width; 7846bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 785836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 786836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Override 787836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public int getIntrinsicHeight() { 788836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return (int)(getMaxIntrinsicHeight() * DEFAULT_VIEW_PORT_SCALE); 789836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 7906bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 7916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private int getMaxIntrinsicHeight() { 7926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni int height = -1; 7936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 7946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable r = mLayerState.mChildren[i]; 7956bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (r.mDrawable == null) { 796836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines continue; 797836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 798836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final int h = r.mDrawable.getIntrinsicHeight(); 799836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (h > height) { 800836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines height = h; 8016bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return height; 8046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 8066bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 807836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public ConstantState getConstantState() { 808836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (mLayerState.canConstantState()) { 809836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mLayerState.mChangingConfigurations = getChangingConfigurations(); 810836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return mLayerState; 811836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 8126bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return null; 8136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 8156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 8166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public Drawable mutate() { 8176bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (!mMutated && super.mutate() == this) { 818836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mLayerState = createConstantState(mLayerState, null); 819836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 820836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final Drawable dr = mLayerState.mChildren[i].mDrawable; 821836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (dr != null) { 822836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines dr.mutate(); 8236bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mMutated = true; 8266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return this; 8286bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 829836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 830836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines /** 831836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines * @hide 832836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines */ 833836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public void clearMutated() { 8346bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni super.clearMutated(); 8356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable[] array = mLayerState.mChildren; 8366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < mLayerState.N_CHILDREN; i++) { 8376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 8386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 8396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni dr.clearMutated(); 840836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 841836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 842836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mMutated = false; 843836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 844836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 8456bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni static class ChildDrawable { 8466bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public Drawable mDrawable; 8476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public int[] mThemeAttrs; 8486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public int mDensity = DisplayMetrics.DENSITY_DEFAULT; 8496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 8506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni ChildDrawable(int density) { 851836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mDensity = density; 852836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 853836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 854836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines ChildDrawable(@NonNull ChildDrawable orig, @NonNull AdaptiveIconDrawable owner, 855836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Nullable Resources res) { 8566bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 8576bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = orig.mDrawable; 8586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable clone; 8596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null) { 8606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ConstantState cs = dr.getConstantState(); 8616bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (cs == null) { 862836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines clone = dr; 863836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } else if (res != null) { 864836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines clone = cs.newDrawable(res); 865836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } else { 866836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines clone = cs.newDrawable(); 8676bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8686bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni clone.setCallback(owner); 8696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni clone.setBounds(dr.getBounds()); 8706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni clone.setLevel(dr.getLevel()); 8716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } else { 8726bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni clone = null; 873836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 874836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 875836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mDrawable = clone; 876836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mThemeAttrs = orig.mThemeAttrs; 877836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 8786bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mDensity = Drawable.resolveDensity(res, orig.mDensity); 8796bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 8816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public boolean canApplyTheme() { 8826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return mThemeAttrs != null 8836bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni || (mDrawable != null && mDrawable.canApplyTheme()); 884836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 885836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 886836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public final void setDensity(int targetDensity) { 887836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (mDensity != targetDensity) { 888836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mDensity = targetDensity; 8896bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8906bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 8926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 8936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni static class LayerState extends ConstantState { 8946bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private int[] mThemeAttrs; 895836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 896836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final static int N_CHILDREN = 2; 897836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines ChildDrawable[] mChildren; 898836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 899836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines int mDensity; 9006bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni int mOpacityOverride = PixelFormat.UNKNOWN; 9016bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Config int mChangingConfigurations; 9036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Config int mChildrenChangingConfigurations; 9046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9056bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni private boolean mCheckedOpacity; 906836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines private int mOpacity; 907836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 908836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines private boolean mCheckedStateful; 909836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines private boolean mIsStateful; 910836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines private boolean mAutoMirrored = false; 9116bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9126bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni LayerState(@Nullable LayerState orig, @NonNull AdaptiveIconDrawable owner, 9136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Nullable Resources res) { 9146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mDensity = Drawable.resolveDensity(res, orig != null ? orig.mDensity : 0); 9156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mChildren = new ChildDrawable[N_CHILDREN]; 9166bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (orig != null) { 917836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final ChildDrawable[] origChildDrawable = orig.mChildren; 918836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 919836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mChangingConfigurations = orig.mChangingConfigurations; 920836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations; 921836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 9226bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < N_CHILDREN; i++) { 9236bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable or = origChildDrawable[i]; 9246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mChildren[i] = new ChildDrawable(or, owner, res); 9256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9276bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mCheckedOpacity = orig.mCheckedOpacity; 928836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mOpacity = orig.mOpacity; 929836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mCheckedStateful = orig.mCheckedStateful; 930836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mIsStateful = orig.mIsStateful; 931836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mAutoMirrored = orig.mAutoMirrored; 932836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mThemeAttrs = orig.mThemeAttrs; 9336bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mOpacityOverride = orig.mOpacityOverride; 9346bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } else { 9356bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < N_CHILDREN; i++) { 9366bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mChildren[i] = new ChildDrawable(mDensity); 9376bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 939836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 940836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 941836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public final void setDensity(int targetDensity) { 942836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (mDensity != targetDensity) { 943836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines mDensity = targetDensity; 9446bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9456bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9466bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9476bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 9486bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public boolean canApplyTheme() { 9496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (mThemeAttrs != null || super.canApplyTheme()) { 950836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return true; 951836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 952836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 953836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final ChildDrawable[] array = mChildren; 954836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines for (int i = 0; i < N_CHILDREN; i++) { 9556bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final ChildDrawable layer = array[i]; 9566bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (layer.canApplyTheme()) { 9576bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return true; 9586bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9596bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9606bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return false; 961836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 962836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 963836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Override 964836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public Drawable newDrawable() { 965836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return new AdaptiveIconDrawable(this, null); 9666bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9676bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9686bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni @Override 9696bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public Drawable newDrawable(@Nullable Resources res) { 9706bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return new AdaptiveIconDrawable(this, res); 9716bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 972836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 973836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines @Override 974836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines public @Config int getChangingConfigurations() { 975836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines return mChangingConfigurations 976836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines | mChildrenChangingConfigurations; 9776bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9786bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 9796bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public final int getOpacity() { 9806bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (mCheckedOpacity) { 9816bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return mOpacity; 9826bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 983836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 984836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines final ChildDrawable[] array = mChildren; 985836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 986836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines // Seek to the first non-null drawable. 987836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines int firstIndex = -1; 9886bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < N_CHILDREN; i++) { 9896bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (array[i].mDrawable != null) { 9906bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni firstIndex = i; 9916bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni break; 9926bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 9936bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 994836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines 995836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines int op; 996836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (firstIndex >= 0) { 997836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines op = array[firstIndex].mDrawable.getOpacity(); 998836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } else { 9996bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni op = PixelFormat.TRANSPARENT; 10006bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 10016bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 10026bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni // Merge all remaining non-null drawables. 10036bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = firstIndex + 1; i < N_CHILDREN; i++) { 10046bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 1005836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines if (dr != null) { 1006836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines op = Drawable.resolveOpacity(op, dr.getOpacity()); 1007836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 1008836c4a58a7f03485ef433dcdb61837cbc0c39735Stephen Hines } 1009932e78e9903342e3494983fd3463084caab4ba42Tim Murray 1010932e78e9903342e3494983fd3463084caab4ba42Tim Murray mOpacity = op; 10116bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mCheckedOpacity = true; 10126bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return op; 10136bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 10146bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 10156bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni public final boolean isStateful() { 1016932e78e9903342e3494983fd3463084caab4ba42Tim Murray if (mCheckedStateful) { 1017932e78e9903342e3494983fd3463084caab4ba42Tim Murray return mIsStateful; 1018932e78e9903342e3494983fd3463084caab4ba42Tim Murray } 1019932e78e9903342e3494983fd3463084caab4ba42Tim Murray 10201d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams final ChildDrawable[] array = mChildren; 10216bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni boolean isStateful = false; 10226bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni for (int i = 0; i < N_CHILDREN; i++) { 10236bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 10246bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null && dr.isStateful()) { 10256bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni isStateful = true; 10266bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni break; 10271d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams } 10281d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams } 10291d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams 103065c80f824711f084c4ece9204f543a7809534294Jason Sams mIsStateful = isStateful; 103165c80f824711f084c4ece9204f543a7809534294Jason Sams mCheckedStateful = true; 103265c80f824711f084c4ece9204f543a7809534294Jason Sams return isStateful; 10331d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams } 10341d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams 10351d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams public final boolean canConstantState() { 10361d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams final ChildDrawable[] array = mChildren; 10371d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams for (int i = 0; i < N_CHILDREN; i++) { 10386bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni final Drawable dr = array[i].mDrawable; 10396bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni if (dr != null && dr.getConstantState() == null) { 10406bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni return false; 10416bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 10426bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 10436bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni 10441d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams // Don't cache the result, this method is not called very often. 1045347697710d033036c533bd6cee409c4b4c19d437Alex Sakhartchouk return true; 10461d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams } 10471d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams 10481d45c47975ab2a8cef6db5a8976276de31e1e8d0Jason Sams public void invalidateCache() { 10496bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mCheckedOpacity = false; 10506bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni mCheckedStateful = false; 10516bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 10526bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni } 10536bdfe0fc5c0845f91cf3ccad961d270ed2a49aa1Yang Ni}