Home | History | Annotate | Download | only in drawable
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.graphics.drawable;
     18 
     19 import org.xmlpull.v1.XmlPullParser;
     20 import org.xmlpull.v1.XmlPullParserException;
     21 
     22 import android.content.res.Resources;
     23 import android.content.res.TypedArray;
     24 import android.graphics.Canvas;
     25 import android.graphics.ColorFilter;
     26 import android.graphics.PixelFormat;
     27 import android.graphics.Rect;
     28 import android.util.AttributeSet;
     29 import android.view.View;
     30 
     31 import java.io.IOException;
     32 
     33 /**
     34  * A Drawable that manages an array of other Drawables. These are drawn in array
     35  * order, so the element with the largest index will be drawn on top.
     36  * <p>
     37  * It can be defined in an XML file with the <code>&lt;layer-list></code> element.
     38  * Each Drawable in the layer is defined in a nested <code>&lt;item></code>. For more
     39  * information, see the guide to <a
     40  * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
     41  *
     42  * @attr ref android.R.styleable#LayerDrawableItem_left
     43  * @attr ref android.R.styleable#LayerDrawableItem_top
     44  * @attr ref android.R.styleable#LayerDrawableItem_right
     45  * @attr ref android.R.styleable#LayerDrawableItem_bottom
     46  * @attr ref android.R.styleable#LayerDrawableItem_drawable
     47  * @attr ref android.R.styleable#LayerDrawableItem_id
     48 */
     49 public class LayerDrawable extends Drawable implements Drawable.Callback {
     50     LayerState mLayerState;
     51 
     52     private int mOpacityOverride = PixelFormat.UNKNOWN;
     53     private int[] mPaddingL;
     54     private int[] mPaddingT;
     55     private int[] mPaddingR;
     56     private int[] mPaddingB;
     57 
     58     private final Rect mTmpRect = new Rect();
     59     private boolean mMutated;
     60 
     61     /**
     62      * Create a new layer drawable with the list of specified layers.
     63      *
     64      * @param layers A list of drawables to use as layers in this new drawable.
     65      */
     66     public LayerDrawable(Drawable[] layers) {
     67         this(layers, null);
     68     }
     69 
     70     /**
     71      * Create a new layer drawable with the specified list of layers and the specified
     72      * constant state.
     73      *
     74      * @param layers The list of layers to add to this drawable.
     75      * @param state The constant drawable state.
     76      */
     77     LayerDrawable(Drawable[] layers, LayerState state) {
     78         this(state, null);
     79         int length = layers.length;
     80         ChildDrawable[] r = new ChildDrawable[length];
     81 
     82         for (int i = 0; i < length; i++) {
     83             r[i] = new ChildDrawable();
     84             r[i].mDrawable = layers[i];
     85             layers[i].setCallback(this);
     86             mLayerState.mChildrenChangingConfigurations |= layers[i].getChangingConfigurations();
     87         }
     88         mLayerState.mNum = length;
     89         mLayerState.mChildren = r;
     90 
     91         ensurePadding();
     92     }
     93 
     94     LayerDrawable() {
     95         this((LayerState) null, null);
     96     }
     97 
     98     LayerDrawable(LayerState state, Resources res) {
     99         LayerState as = createConstantState(state, res);
    100         mLayerState = as;
    101         if (as.mNum > 0) {
    102             ensurePadding();
    103         }
    104     }
    105 
    106     LayerState createConstantState(LayerState state, Resources res) {
    107         return new LayerState(state, this, res);
    108     }
    109 
    110     @Override
    111     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
    112             throws XmlPullParserException, IOException {
    113         super.inflate(r, parser, attrs);
    114 
    115         int type;
    116 
    117         TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.LayerDrawable);
    118 
    119         mOpacityOverride = a.getInt(com.android.internal.R.styleable.LayerDrawable_opacity,
    120                 PixelFormat.UNKNOWN);
    121 
    122         a.recycle();
    123 
    124         final int innerDepth = parser.getDepth() + 1;
    125         int depth;
    126         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
    127                 && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
    128             if (type != XmlPullParser.START_TAG) {
    129                 continue;
    130             }
    131 
    132             if (depth > innerDepth || !parser.getName().equals("item")) {
    133                 continue;
    134             }
    135 
    136             a = r.obtainAttributes(attrs,
    137                     com.android.internal.R.styleable.LayerDrawableItem);
    138 
    139             int left = a.getDimensionPixelOffset(
    140                     com.android.internal.R.styleable.LayerDrawableItem_left, 0);
    141             int top = a.getDimensionPixelOffset(
    142                     com.android.internal.R.styleable.LayerDrawableItem_top, 0);
    143             int right = a.getDimensionPixelOffset(
    144                     com.android.internal.R.styleable.LayerDrawableItem_right, 0);
    145             int bottom = a.getDimensionPixelOffset(
    146                     com.android.internal.R.styleable.LayerDrawableItem_bottom, 0);
    147             int drawableRes = a.getResourceId(
    148                     com.android.internal.R.styleable.LayerDrawableItem_drawable, 0);
    149             int id = a.getResourceId(com.android.internal.R.styleable.LayerDrawableItem_id,
    150                     View.NO_ID);
    151 
    152             a.recycle();
    153 
    154             Drawable dr;
    155             if (drawableRes != 0) {
    156                 dr = r.getDrawable(drawableRes);
    157             } else {
    158                 while ((type = parser.next()) == XmlPullParser.TEXT) {
    159                 }
    160                 if (type != XmlPullParser.START_TAG) {
    161                     throw new XmlPullParserException(parser.getPositionDescription()
    162                             + ": <item> tag requires a 'drawable' attribute or "
    163                             + "child tag defining a drawable");
    164                 }
    165                 dr = Drawable.createFromXmlInner(r, parser, attrs);
    166             }
    167 
    168             addLayer(dr, id, left, top, right, bottom);
    169         }
    170 
    171         ensurePadding();
    172         onStateChange(getState());
    173     }
    174 
    175     /**
    176      * Add a new layer to this drawable. The new layer is identified by an id.
    177      *
    178      * @param layer The drawable to add as a layer.
    179      * @param id The id of the new layer.
    180      * @param left The left padding of the new layer.
    181      * @param top The top padding of the new layer.
    182      * @param right The right padding of the new layer.
    183      * @param bottom The bottom padding of the new layer.
    184      */
    185     private void addLayer(Drawable layer, int id, int left, int top, int right, int bottom) {
    186         final LayerState st = mLayerState;
    187         int N = st.mChildren != null ? st.mChildren.length : 0;
    188         int i = st.mNum;
    189         if (i >= N) {
    190             ChildDrawable[] nu = new ChildDrawable[N + 10];
    191             if (i > 0) {
    192                 System.arraycopy(st.mChildren, 0, nu, 0, i);
    193             }
    194             st.mChildren = nu;
    195         }
    196 
    197         mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations();
    198 
    199         ChildDrawable childDrawable = new ChildDrawable();
    200         st.mChildren[i] = childDrawable;
    201         childDrawable.mId = id;
    202         childDrawable.mDrawable = layer;
    203         childDrawable.mInsetL = left;
    204         childDrawable.mInsetT = top;
    205         childDrawable.mInsetR = right;
    206         childDrawable.mInsetB = bottom;
    207         st.mNum++;
    208 
    209         layer.setCallback(this);
    210     }
    211 
    212     /**
    213      * Look for a layer with the given id, and returns its {@link Drawable}.
    214      *
    215      * @param id The layer ID to search for.
    216      * @return The {@link Drawable} of the layer that has the given id in the hierarchy or null.
    217      */
    218     public Drawable findDrawableByLayerId(int id) {
    219         final ChildDrawable[] layers = mLayerState.mChildren;
    220 
    221         for (int i = mLayerState.mNum - 1; i >= 0; i--) {
    222             if (layers[i].mId == id) {
    223                 return layers[i].mDrawable;
    224             }
    225         }
    226 
    227         return null;
    228     }
    229 
    230     /**
    231      * Sets the ID of a layer.
    232      *
    233      * @param index The index of the layer which will received the ID.
    234      * @param id The ID to assign to the layer.
    235      */
    236     public void setId(int index, int id) {
    237         mLayerState.mChildren[index].mId = id;
    238     }
    239 
    240     /**
    241      * Returns the number of layers contained within this.
    242      * @return The number of layers.
    243      */
    244     public int getNumberOfLayers() {
    245         return mLayerState.mNum;
    246     }
    247 
    248     /**
    249      * Returns the drawable at the specified layer index.
    250      *
    251      * @param index The layer index of the drawable to retrieve.
    252      *
    253      * @return The {@link android.graphics.drawable.Drawable} at the specified layer index.
    254      */
    255     public Drawable getDrawable(int index) {
    256         return mLayerState.mChildren[index].mDrawable;
    257     }
    258 
    259     /**
    260      * Returns the id of the specified layer.
    261      *
    262      * @param index The index of the layer.
    263      *
    264      * @return The id of the layer or {@link android.view.View#NO_ID} if the layer has no id.
    265      */
    266     public int getId(int index) {
    267         return mLayerState.mChildren[index].mId;
    268     }
    269 
    270     /**
    271      * Sets (or replaces) the {@link Drawable} for the layer with the given id.
    272      *
    273      * @param id The layer ID to search for.
    274      * @param drawable The replacement {@link Drawable}.
    275      * @return Whether the {@link Drawable} was replaced (could return false if
    276      *         the id was not found).
    277      */
    278     public boolean setDrawableByLayerId(int id, Drawable drawable) {
    279         final ChildDrawable[] layers = mLayerState.mChildren;
    280 
    281         for (int i = mLayerState.mNum - 1; i >= 0; i--) {
    282             if (layers[i].mId == id) {
    283                 if (layers[i].mDrawable != null) {
    284                     if (drawable != null) {
    285                         Rect bounds = layers[i].mDrawable.getBounds();
    286                         drawable.setBounds(bounds);
    287                     }
    288                     layers[i].mDrawable.setCallback(null);
    289                 }
    290                 if (drawable != null) {
    291                     drawable.setCallback(this);
    292                 }
    293                 layers[i].mDrawable = drawable;
    294                 return true;
    295             }
    296         }
    297 
    298         return false;
    299     }
    300 
    301     /** Specify modifiers to the bounds for the drawable[index].
    302         left += l
    303         top += t;
    304         right -= r;
    305         bottom -= b;
    306     */
    307     public void setLayerInset(int index, int l, int t, int r, int b) {
    308         ChildDrawable childDrawable = mLayerState.mChildren[index];
    309         childDrawable.mInsetL = l;
    310         childDrawable.mInsetT = t;
    311         childDrawable.mInsetR = r;
    312         childDrawable.mInsetB = b;
    313     }
    314 
    315     // overrides from Drawable.Callback
    316 
    317     public void invalidateDrawable(Drawable who) {
    318         final Callback callback = getCallback();
    319         if (callback != null) {
    320             callback.invalidateDrawable(this);
    321         }
    322     }
    323 
    324     public void scheduleDrawable(Drawable who, Runnable what, long when) {
    325         final Callback callback = getCallback();
    326         if (callback != null) {
    327             callback.scheduleDrawable(this, what, when);
    328         }
    329     }
    330 
    331     public void unscheduleDrawable(Drawable who, Runnable what) {
    332         final Callback callback = getCallback();
    333         if (callback != null) {
    334             callback.unscheduleDrawable(this, what);
    335         }
    336     }
    337 
    338     // overrides from Drawable
    339 
    340     @Override
    341     public void draw(Canvas canvas) {
    342         final ChildDrawable[] array = mLayerState.mChildren;
    343         final int N = mLayerState.mNum;
    344         for (int i=0; i<N; i++) {
    345             array[i].mDrawable.draw(canvas);
    346         }
    347     }
    348 
    349     @Override
    350     public int getChangingConfigurations() {
    351         return super.getChangingConfigurations()
    352                 | mLayerState.mChangingConfigurations
    353                 | mLayerState.mChildrenChangingConfigurations;
    354     }
    355 
    356     @Override
    357     public boolean getPadding(Rect padding) {
    358         // Arbitrarily get the padding from the first image.
    359         // Technically we should maybe do something more intelligent,
    360         // like take the max padding of all the images.
    361         padding.left = 0;
    362         padding.top = 0;
    363         padding.right = 0;
    364         padding.bottom = 0;
    365         final ChildDrawable[] array = mLayerState.mChildren;
    366         final int N = mLayerState.mNum;
    367         for (int i=0; i<N; i++) {
    368             reapplyPadding(i, array[i]);
    369             padding.left += mPaddingL[i];
    370             padding.top += mPaddingT[i];
    371             padding.right += mPaddingR[i];
    372             padding.bottom += mPaddingB[i];
    373         }
    374         return true;
    375     }
    376 
    377     @Override
    378     public boolean setVisible(boolean visible, boolean restart) {
    379         boolean changed = super.setVisible(visible, restart);
    380         final ChildDrawable[] array = mLayerState.mChildren;
    381         final int N = mLayerState.mNum;
    382         for (int i=0; i<N; i++) {
    383             array[i].mDrawable.setVisible(visible, restart);
    384         }
    385         return changed;
    386     }
    387 
    388     @Override
    389     public void setDither(boolean dither) {
    390         final ChildDrawable[] array = mLayerState.mChildren;
    391         final int N = mLayerState.mNum;
    392         for (int i=0; i<N; i++) {
    393             array[i].mDrawable.setDither(dither);
    394         }
    395     }
    396 
    397     @Override
    398     public void setAlpha(int alpha) {
    399         final ChildDrawable[] array = mLayerState.mChildren;
    400         final int N = mLayerState.mNum;
    401         for (int i=0; i<N; i++) {
    402             array[i].mDrawable.setAlpha(alpha);
    403         }
    404     }
    405 
    406     @Override
    407     public void setColorFilter(ColorFilter cf) {
    408         final ChildDrawable[] array = mLayerState.mChildren;
    409         final int N = mLayerState.mNum;
    410         for (int i=0; i<N; i++) {
    411             array[i].mDrawable.setColorFilter(cf);
    412         }
    413     }
    414 
    415     /**
    416      * Sets the opacity of this drawable directly, instead of collecting the states from
    417      * the layers
    418      *
    419      * @param opacity The opacity to use, or {@link PixelFormat#UNKNOWN PixelFormat.UNKNOWN}
    420      * for the default behavior
    421      *
    422      * @see PixelFormat#UNKNOWN
    423      * @see PixelFormat#TRANSLUCENT
    424      * @see PixelFormat#TRANSPARENT
    425      * @see PixelFormat#OPAQUE
    426      */
    427     public void setOpacity(int opacity) {
    428         mOpacityOverride = opacity;
    429     }
    430 
    431     @Override
    432     public int getOpacity() {
    433         if (mOpacityOverride != PixelFormat.UNKNOWN) {
    434             return mOpacityOverride;
    435         }
    436         return mLayerState.getOpacity();
    437     }
    438 
    439     @Override
    440     public boolean isStateful() {
    441         return mLayerState.isStateful();
    442     }
    443 
    444     @Override
    445     protected boolean onStateChange(int[] state) {
    446         final ChildDrawable[] array = mLayerState.mChildren;
    447         final int N = mLayerState.mNum;
    448         boolean paddingChanged = false;
    449         boolean changed = false;
    450         for (int i=0; i<N; i++) {
    451             final ChildDrawable r = array[i];
    452             if (r.mDrawable.setState(state)) {
    453                 changed = true;
    454             }
    455             if (reapplyPadding(i, r)) {
    456                 paddingChanged = true;
    457             }
    458         }
    459         if (paddingChanged) {
    460             onBoundsChange(getBounds());
    461         }
    462         return changed;
    463     }
    464 
    465     @Override
    466     protected boolean onLevelChange(int level) {
    467         final ChildDrawable[] array = mLayerState.mChildren;
    468         final int N = mLayerState.mNum;
    469         boolean paddingChanged = false;
    470         boolean changed = false;
    471         for (int i=0; i<N; i++) {
    472             final ChildDrawable r = array[i];
    473             if (r.mDrawable.setLevel(level)) {
    474                 changed = true;
    475             }
    476             if (reapplyPadding(i, r)) {
    477                 paddingChanged = true;
    478             }
    479         }
    480         if (paddingChanged) {
    481             onBoundsChange(getBounds());
    482         }
    483         return changed;
    484     }
    485 
    486     @Override
    487     protected void onBoundsChange(Rect bounds) {
    488         final ChildDrawable[] array = mLayerState.mChildren;
    489         final int N = mLayerState.mNum;
    490         int padL=0, padT=0, padR=0, padB=0;
    491         for (int i=0; i<N; i++) {
    492             final ChildDrawable r = array[i];
    493             r.mDrawable.setBounds(bounds.left + r.mInsetL + padL,
    494                                   bounds.top + r.mInsetT + padT,
    495                                   bounds.right - r.mInsetR - padR,
    496                                   bounds.bottom - r.mInsetB - padB);
    497             padL += mPaddingL[i];
    498             padR += mPaddingR[i];
    499             padT += mPaddingT[i];
    500             padB += mPaddingB[i];
    501         }
    502     }
    503 
    504     @Override
    505     public int getIntrinsicWidth() {
    506         int width = -1;
    507         final ChildDrawable[] array = mLayerState.mChildren;
    508         final int N = mLayerState.mNum;
    509         int padL=0, padR=0;
    510         for (int i=0; i<N; i++) {
    511             final ChildDrawable r = array[i];
    512             int w = r.mDrawable.getIntrinsicWidth()
    513                   + r.mInsetL + r.mInsetR + padL + padR;
    514             if (w > width) {
    515                 width = w;
    516             }
    517             padL += mPaddingL[i];
    518             padR += mPaddingR[i];
    519         }
    520         return width;
    521     }
    522 
    523     @Override
    524     public int getIntrinsicHeight() {
    525         int height = -1;
    526         final ChildDrawable[] array = mLayerState.mChildren;
    527         final int N = mLayerState.mNum;
    528         int padT=0, padB=0;
    529         for (int i=0; i<N; i++) {
    530             final ChildDrawable r = array[i];
    531             int h = r.mDrawable.getIntrinsicHeight() + r.mInsetT + r.mInsetB + + padT + padB;
    532             if (h > height) {
    533                 height = h;
    534             }
    535             padT += mPaddingT[i];
    536             padB += mPaddingB[i];
    537         }
    538         return height;
    539     }
    540 
    541     private boolean reapplyPadding(int i, ChildDrawable r) {
    542         final Rect rect = mTmpRect;
    543         r.mDrawable.getPadding(rect);
    544         if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i] ||
    545                 rect.right != mPaddingR[i] || rect.bottom != mPaddingB[i]) {
    546             mPaddingL[i] = rect.left;
    547             mPaddingT[i] = rect.top;
    548             mPaddingR[i] = rect.right;
    549             mPaddingB[i] = rect.bottom;
    550             return true;
    551         }
    552         return false;
    553     }
    554 
    555     private void ensurePadding() {
    556         final int N = mLayerState.mNum;
    557         if (mPaddingL != null && mPaddingL.length >= N) {
    558             return;
    559         }
    560         mPaddingL = new int[N];
    561         mPaddingT = new int[N];
    562         mPaddingR = new int[N];
    563         mPaddingB = new int[N];
    564     }
    565 
    566     @Override
    567     public ConstantState getConstantState() {
    568         if (mLayerState.canConstantState()) {
    569             mLayerState.mChangingConfigurations = getChangingConfigurations();
    570             return mLayerState;
    571         }
    572         return null;
    573     }
    574 
    575     @Override
    576     public Drawable mutate() {
    577         if (!mMutated && super.mutate() == this) {
    578             final ChildDrawable[] array = mLayerState.mChildren;
    579             final int N = mLayerState.mNum;
    580             for (int i = 0; i < N; i++) {
    581                 array[i].mDrawable.mutate();
    582             }
    583             mMutated = true;
    584         }
    585         return this;
    586     }
    587 
    588     static class ChildDrawable {
    589         public Drawable mDrawable;
    590         public int mInsetL, mInsetT, mInsetR, mInsetB;
    591         public int mId;
    592     }
    593 
    594     static class LayerState extends ConstantState {
    595         int mNum;
    596         ChildDrawable[] mChildren;
    597 
    598         int mChangingConfigurations;
    599         int mChildrenChangingConfigurations;
    600 
    601         private boolean mHaveOpacity = false;
    602         private int mOpacity;
    603 
    604         private boolean mHaveStateful = false;
    605         private boolean mStateful;
    606 
    607         private boolean mCheckedConstantState;
    608         private boolean mCanConstantState;
    609 
    610         LayerState(LayerState orig, LayerDrawable owner, Resources res) {
    611             if (orig != null) {
    612                 final ChildDrawable[] origChildDrawable = orig.mChildren;
    613                 final int N = orig.mNum;
    614 
    615                 mNum = N;
    616                 mChildren = new ChildDrawable[N];
    617 
    618                 mChangingConfigurations = orig.mChangingConfigurations;
    619                 mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
    620 
    621                 for (int i = 0; i < N; i++) {
    622                     final ChildDrawable r = mChildren[i] = new ChildDrawable();
    623                     final ChildDrawable or = origChildDrawable[i];
    624                     if (res != null) {
    625                         r.mDrawable = or.mDrawable.getConstantState().newDrawable(res);
    626                     } else {
    627                         r.mDrawable = or.mDrawable.getConstantState().newDrawable();
    628                     }
    629                     r.mDrawable.setCallback(owner);
    630                     r.mInsetL = or.mInsetL;
    631                     r.mInsetT = or.mInsetT;
    632                     r.mInsetR = or.mInsetR;
    633                     r.mInsetB = or.mInsetB;
    634                     r.mId = or.mId;
    635                 }
    636 
    637                 mHaveOpacity = orig.mHaveOpacity;
    638                 mOpacity = orig.mOpacity;
    639                 mHaveStateful = orig.mHaveStateful;
    640                 mStateful = orig.mStateful;
    641                 mCheckedConstantState = mCanConstantState = true;
    642             } else {
    643                 mNum = 0;
    644                 mChildren = null;
    645             }
    646         }
    647 
    648         @Override
    649         public Drawable newDrawable() {
    650             return new LayerDrawable(this, null);
    651         }
    652 
    653         @Override
    654         public Drawable newDrawable(Resources res) {
    655             return new LayerDrawable(this, res);
    656         }
    657 
    658         @Override
    659         public int getChangingConfigurations() {
    660             return mChangingConfigurations;
    661         }
    662 
    663         public final int getOpacity() {
    664             if (mHaveOpacity) {
    665                 return mOpacity;
    666             }
    667 
    668             final int N = mNum;
    669             int op = N > 0 ? mChildren[0].mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
    670             for (int i = 1; i < N; i++) {
    671                 op = Drawable.resolveOpacity(op, mChildren[i].mDrawable.getOpacity());
    672             }
    673             mOpacity = op;
    674             mHaveOpacity = true;
    675             return op;
    676         }
    677 
    678         public final boolean isStateful() {
    679             if (mHaveStateful) {
    680                 return mStateful;
    681             }
    682 
    683             boolean stateful = false;
    684             final int N = mNum;
    685             for (int i = 0; i < N; i++) {
    686                 if (mChildren[i].mDrawable.isStateful()) {
    687                     stateful = true;
    688                     break;
    689                 }
    690             }
    691 
    692             mStateful = stateful;
    693             mHaveStateful = true;
    694             return stateful;
    695         }
    696 
    697         public synchronized boolean canConstantState() {
    698             if (!mCheckedConstantState && mChildren != null) {
    699                 mCanConstantState = true;
    700                 final int N = mNum;
    701                 for (int i=0; i<N; i++) {
    702                     if (mChildren[i].mDrawable.getConstantState() == null) {
    703                         mCanConstantState = false;
    704                         break;
    705                     }
    706                 }
    707                 mCheckedConstantState = true;
    708             }
    709 
    710             return mCanConstantState;
    711         }
    712     }
    713 }
    714 
    715