2012-02-15 78 views
0

这是实现图层概念的代码。即动态添加图层。我在来自Drawable.callback的//旁边的mcallback中出现错误。 有人可以帮我解决它。它说mcallback不能解析成变量。 在此先感谢有人可以帮我解决这个代码中的mcallback中的错误

package com.cts.drawable; 


import org.xmlpull.v1.XmlPullParser; 
import org.xmlpull.v1.XmlPullParserException; 

import android.content.res.Resources; 
import android.content.res.TypedArray; 
import android.graphics.*; 
import android.graphics.drawable.Drawable; 
import android.graphics.drawable.Drawable.Callback; 
import android.util.AttributeSet; 
import android.view.View; 

import java.io.IOException; 

/** 
* A Drawable that manages an array of other Drawables. These are drawn in array 
* order, so the element with the largest index will be drawn on top. 
* <p> 
* It can be defined in an XML file with the <code><layer-list> element. 
* Each Drawable in the layer is defined in a nested <code><item>. 
* </p> 
* 
* @attr ref android.R.styleable#LayerDrawableItem_left 
* @attr ref android.R.styleable#LayerDrawableItem_top 
    * @attr ref android.R.styleable#LayerDrawableItem_right 
* @attr ref android.R.styleable#LayerDrawableItem_bottom 
* @attr ref android.R.styleable#LayerDrawableItem_drawable 
    * @attr ref android.R.styleable#LayerDrawableItem_id 
*/ 
public class LayerDrawable extends Drawable implements Drawable.Callback { 
LayerState mLayerState; 

private int[] mPaddingL; 
private int[] mPaddingT; 
private int[] mPaddingR; 
private int[] mPaddingB; 

private final Rect mTmpRect = new Rect(); 
private boolean mMutated; 



/** 
* Create a new layer drawable with the list of specified layers. 
* 
* @param layers A list of drawables to use as layers in this new drawable. 
*/ 
public LayerDrawable(Drawable[] layers) { 
    this(layers, null); 
} 

/** 
* Create a new layer drawable with the specified list of layers and the specified 
* constant state. 
* 
* @param layers The list of layers to add to this drawable. 
* @param state The constant drawable state. 
*/ 
LayerDrawable(Drawable[] layers, LayerState state) { 
    this(state, null); 
    int length = layers.length; 
    ChildDrawable[] r = new ChildDrawable[length]; 

    for (int i = 0; i < length; i++) { 
     r[i] = new ChildDrawable(); 
     r[i].mDrawable = layers[i]; 
     layers[i].setCallback(this); 
     mLayerState.mChildrenChangingConfigurations |= layers    [i].getChangingConfigurations(); 
         } 
     mLayerState.mNum = length; 
     mLayerState.mChildren = r; 

    ensurePadding(); 
    } 

    LayerDrawable() { 
    this((LayerState) null, null); 
    } 

    LayerDrawable(LayerState state, Resources res) { 
    LayerState as = createConstantState(state, res); 
    mLayerState = as; 
    if (as.mNum > 0) { 
     ensurePadding(); 
    } 
    } 

    LayerState createConstantState(LayerState state, Resources res) { 
    return new LayerState(state, this, res); 
    } 

    @Override 
    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 
     throws XmlPullParserException, IOException { 
    super.inflate(r, parser, attrs); 

    int type; 

    final int innerDepth = parser.getDepth() + 1; 
    int depth; 
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 
      && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { 
     if (type != XmlPullParser.START_TAG) { 
      continue; 
     } 

     if (depth > innerDepth || !parser.getName().equals("item")) { 
      continue; 
     } 

     TypedArray a = r.obtainAttributes(attrs, 
       R.styleable.LayerDrawableItem); 

     int left = a.getDimensionPixelOffset(
       R.styleable.LayerDrawableItem_LayerDrawableItem_left, 0); 
     int top = a.getDimensionPixelOffset(
       R.styleable.LayerDrawableItem_LayerDrawableItem_top, 0); 
     int right = a.getDimensionPixelOffset(
       R.styleable.LayerDrawableItem_LayerDrawableItem_right, 0); 
     int bottom = a.getDimensionPixelOffset(
       R.styleable.LayerDrawableItem_LayerDrawableItem_bottom, 0); 
     int drawableRes = a.getResourceId(
       R.styleable.LayerDrawableItem_LayerDrawableItem_drawable, 0); 
     int id = a.getResourceId(R.styleable.LayerDrawableItem_LayerDrawableItem_id, 
       View.NO_ID); 

     a.recycle(); 

     Drawable dr; 
     if (drawableRes != 0) { 
      dr = r.getDrawable(drawableRes); 
     } else { 
      while ((type = parser.next()) == XmlPullParser.TEXT) { 
      } 
      if (type != XmlPullParser.START_TAG) { 
       throw new XmlPullParserException(parser.getPositionDescription() 
         + ": <item> tag requires a 'drawable' attribute or " 
         + "child tag defining a drawable"); 
      } 
      dr = Drawable.createFromXmlInner(r, parser, attrs); 
     } 

     addLayer(dr, id, left, top, right, bottom); 
     } 

     ensurePadding(); 
     onStateChange(getState()); 
     } 

    /** 
    * Add a new layer to this drawable. The new layer is identified by an id. 
    * 
    * @param layer The drawable to add as a layer. 
    * @param id The id of the new layer. 
    * @param left The left padding of the new layer. 
    * @param top The top padding of the new layer. 
    * @param right The right padding of the new layer. 
    * @param bottom The bottom padding of the new layer. 
    */ 
    private void addLayer(Drawable layer, int id, int left, int top, int right, int bottom) { 
    final LayerState st = mLayerState; 
    int N = st.mChildren != null ? st.mChildren.length : 0; 
    int i = st.mNum; 
    if (i >= N) { 
     ChildDrawable[] nu = new ChildDrawable[N + 10]; 
     if (i > 0) { 
      System.arraycopy(st.mChildren, 0, nu, 0, i); 
     } 
     st.mChildren = nu; 
    } 

    mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations(); 

    ChildDrawable childDrawable = new ChildDrawable(); 
    st.mChildren[i] = childDrawable; 
    childDrawable.mId = id; 
    childDrawable.mDrawable = layer; 
    childDrawable.mInsetL = left; 
    childDrawable.mInsetT = top; 
    childDrawable.mInsetR = right; 
    childDrawable.mInsetB = bottom; 
    st.mNum++; 

    layer.setCallback(this); 
    } 

     /** 
    * Look for a layer with the given id, and returns its {@link Drawable}. 
    * 
    * @param id The layer ID to search for. 
    * @return The {@link Drawable} of the layer that has the given id in the hierarchy or null. 
    */ 
    public Drawable findDrawableByLayerId(int id) { 
    final ChildDrawable[] layers = mLayerState.mChildren; 

    for (int i = mLayerState.mNum - 1; i >= 0; i--) { 
     if (layers[i].mId == id) { 
      return layers[i].mDrawable; 
     } 
    } 

    return null; 
    } 

    /** 
    * Sets the ID of a layer. 
    * 
    * @param index The index of the layer which will received the ID. 
    * @param id The ID to assign to the layer. 
    */ 
    public void setId(int index, int id) { 
    mLayerState.mChildren[index].mId = id; 
    } 

    /** 
    * Returns the number of layers contained within this. 
    * @return The number of layers. 
    */ 
    public int getNumberOfLayers() { 
    return mLayerState.mNum; 
    } 

    /** 
    * Returns the drawable at the specified layer index. 
    * 
    * @param index The layer index of the drawable to retrieve. 
    * 
    * @return The {@link android.graphics.drawable.Drawable} at the specified layer index. 
    */ 
    public Drawable getDrawable(int index) { 
    return mLayerState.mChildren[index].mDrawable; 
    } 

    /** 
    * Returns the id of the specified layer. 
    * 
    * @param index The index of the layer. 
    * 
    * @return The id of the layer or {@link android.view.View#NO_ID} if the layer has no id. 
    */ 
    public int getId(int index) { 
    return mLayerState.mChildren[index].mId; 
    } 

    /** 
    * Sets (or replaces) the {@link Drawable} for the layer with the given id. 
    * 
    * @param id The layer ID to search for. 
    * @param drawable The replacement {@link Drawable}. 
    * @return Whether the {@link Drawable} was replaced (could return false if 
    *   the id was not found). 
    */ 
    public boolean setDrawableByLayerId(int id, Drawable drawable) { 
    final ChildDrawable[] layers = mLayerState.mChildren; 

    for (int i = mLayerState.mNum - 1; i >= 0; i--) { 
     if (layers[i].mId == id) { 
      layers[i].mDrawable = drawable; 
      return true; 
     } 
    } 

    return false; 
    } 

    /** Specify modifiers to the bounds for the drawable[index]. 
    left += l 
    top += t; 
    right -= r; 
    bottom -= b; 
    */ 
    public void setLayerInset(int index, int l, int t, int r, int b) { 
    ChildDrawable childDrawable = mLayerState.mChildren[index]; 
    childDrawable.mInsetL = l; 
    childDrawable.mInsetT = t; 
    childDrawable.mInsetR = r; 
    childDrawable.mInsetB = b; 
    } 

    // overrides from Drawable.Callback 

    public void invalidateDrawable(Drawable who) { 
    if (mCallback != null) { 
     mCallback.invalidateDrawable(this); 
    } 
    } 
    public void scheduleDrawable(Drawable who, Runnable what, long when) { 
    if (mCallback != null) { 
     mCallback.scheduleDrawable(this, what, when); 
    } 
    } 
    public void unscheduleDrawable(Drawable who, Runnable what) { 
    if (mCallback != null) { 
     mCallback.unscheduleDrawable(this, what); 
    } 
    } 

    // overrides from Drawable 

    @Override 
    public void draw(Canvas canvas) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    for (int i=0; i<N; i++) { 
     array[i].mDrawable.draw(canvas); 
    } 
    } 

    @Override 
    public int getChangingConfigurations() { 
    return super.getChangingConfigurations() 
      | mLayerState.mChangingConfigurations 
      | mLayerState.mChildrenChangingConfigurations; 
    } 

    @Override 
    public boolean getPadding(Rect padding) { 
    // Arbitrarily get the padding from the first image. 
    // Technically we should maybe do something more intelligent, 
    // like take the max padding of all the images. 
    padding.left = 0; 
    padding.top = 0; 
    padding.right = 0; 
    padding.bottom = 0; 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    for (int i=0; i<N; i++) { 
     reapplyPadding(i, array[i]); 
     padding.left += mPaddingL[i]; 
     padding.top += mPaddingT[i]; 
     padding.right += mPaddingR[i]; 
     padding.bottom += mPaddingB[i]; 
    } 
    return true; 
    } 

    @Override 
    public boolean setVisible(boolean visible, boolean restart) { 
    boolean changed = super.setVisible(visible, restart); 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    for (int i=0; i<N; i++) { 
     array[i].mDrawable.setVisible(visible, restart); 
    } 
    return changed; 
    } 

    @Override 
    public void setDither(boolean dither) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    for (int i=0; i<N; i++) { 
     array[i].mDrawable.setDither(dither); 
    } 
    } 

    @Override 
    public void setAlpha(int alpha) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    for (int i=0; i<N; i++) { 
     array[i].mDrawable.setAlpha(alpha); 
    } 
    } 

    @Override 
    public void setColorFilter(ColorFilter cf) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    for (int i=0; i<N; i++) { 
     array[i].mDrawable.setColorFilter(cf); 
    } 
    } 

    @Override 
    public int getOpacity() { 
    return mLayerState.getOpacity(); 
    } 

    @Override 
    public boolean isStateful() { 
    return mLayerState.isStateful(); 
    } 

    @Override 
    protected boolean onStateChange(int[] state) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    boolean paddingChanged = false; 
    boolean changed = false; 
    for (int i=0; i<N; i++) { 
     final ChildDrawable r = array[i]; 
     if (r.mDrawable.setState(state)) { 
      changed = true; 
     } 
     if (reapplyPadding(i, r)) { 
      paddingChanged = true; 
     } 
    } 
    if (paddingChanged) { 
     onBoundsChange(getBounds()); 
    } 
    return changed; 
    } 

    @Override 
    protected boolean onLevelChange(int level) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    boolean paddingChanged = false; 
    boolean changed = false; 
    for (int i=0; i<N; i++) { 
     final ChildDrawable r = array[i]; 
     if (r.mDrawable.setLevel(level)) { 
      changed = true; 
     } 
     if (reapplyPadding(i, r)) { 
      paddingChanged = true; 
     } 
    } 
    if (paddingChanged) { 
     onBoundsChange(getBounds()); 
    } 
    return changed; 
    } 

    @Override 
    protected void onBoundsChange(Rect bounds) { 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    int padL=0, padT=0, padR=0, padB=0; 
    for (int i=0; i<N; i++) { 
     final ChildDrawable r = array[i]; 
     r.mDrawable.setBounds(bounds.left + r.mInsetL + padL, 
           bounds.top + r.mInsetT + padT, 
           bounds.right - r.mInsetR - padR, 
           bounds.bottom - r.mInsetB - padB); 
     padL += mPaddingL[i]; 
     padR += mPaddingR[i]; 
     padT += mPaddingT[i]; 
     padB += mPaddingB[i]; 
     } 
     } 

     @Override 
     public int getIntrinsicWidth() { 
    int width = -1; 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    int padL=0, padR=0; 
    for (int i=0; i<N; i++) { 
     final ChildDrawable r = array[i]; 
     int w = r.mDrawable.getIntrinsicWidth() 
       + r.mInsetL + r.mInsetR + padL + padR; 
     if (w > width) { 
      width = w; 
     } 
     padL += mPaddingL[i]; 
     padR += mPaddingR[i]; 
     } 
     return width; 
     } 

    @Override 
    public int getIntrinsicHeight() { 
    int height = -1; 
    final ChildDrawable[] array = mLayerState.mChildren; 
    final int N = mLayerState.mNum; 
    int padT=0, padB=0; 
    for (int i=0; i<N; i++) { 
     final ChildDrawable r = array[i]; 
     int h = r.mDrawable.getIntrinsicHeight() + r.mInsetT + r.mInsetB + + padT + padB; 
     if (h > height) { 
      height = h; 
     } 
     padT += mPaddingT[i]; 
     padB += mPaddingB[i]; 
    } 
    return height; 
    } 

    private boolean reapplyPadding(int i, ChildDrawable r) { 
    final Rect rect = mTmpRect; 
    r.mDrawable.getPadding(rect); 
    if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i] || 
      rect.right != mPaddingR[i] || rect.bottom != mPaddingB[i]) { 
     mPaddingL[i] = rect.left; 
     mPaddingT[i] = rect.top; 
     mPaddingR[i] = rect.right; 
     mPaddingB[i] = rect.bottom; 
     return true; 
    } 
    return false; 
     } 

     private void ensurePadding() { 
    final int N = mLayerState.mNum; 
    if (mPaddingL != null && mPaddingL.length >= N) { 
     return; 
    } 
    mPaddingL = new int[N]; 
    mPaddingT = new int[N]; 
    mPaddingR = new int[N]; 
    mPaddingB = new int[N]; 
    } 

     @Override 
     public ConstantState getConstantState() { 
    if (mLayerState.canConstantState()) { 
     mLayerState.mChangingConfigurations = super.getChangingConfigurations(); 
     return mLayerState; 
    } 
    return null; 
     } 

    @Override 
    public Drawable mutate() { 
    if (!mMutated && super.mutate() == this) { 
     final ChildDrawable[] array = mLayerState.mChildren; 
     final int N = mLayerState.mNum; 
     for (int i = 0; i < N; i++) { 
      array[i].mDrawable.mutate(); 
     } 
     mMutated = true; 
    } 
    return this; 
     } 

    static class ChildDrawable { 
    public Drawable mDrawable; 
    public int mInsetL, mInsetT, mInsetR, mInsetB; 
    public int mId; 
    } 

    static class LayerState extends ConstantState { 
    int mNum; 
    ChildDrawable[] mChildren; 

    int mChangingConfigurations; 
    int mChildrenChangingConfigurations; 

    private boolean mHaveOpacity = false; 
    private int mOpacity; 

    private boolean mHaveStateful = false; 
    private boolean mStateful; 

    private boolean mCheckedConstantState; 
    private boolean mCanConstantState; 

    LayerState(LayerState orig, LayerDrawable owner, Resources res) { 
     if (orig != null) { 
      final ChildDrawable[] origChildDrawable = orig.mChildren; 
      final int N = orig.mNum; 

      mNum = N; 
      mChildren = new ChildDrawable[N]; 

      mChangingConfigurations = orig.mChangingConfigurations; 
      mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations; 

      for (int i = 0; i < N; i++) { 
       final ChildDrawable r = mChildren[i] = new ChildDrawable(); 
       final ChildDrawable or = origChildDrawable[i]; 
       if (res != null) { 
        r.mDrawable = or.mDrawable.getConstantState().newDrawable(res); 
       } else { 
        r.mDrawable = or.mDrawable.getConstantState().newDrawable(); 
       } 
       r.mDrawable.setCallback(owner); 
       r.mInsetL = or.mInsetL; 
       r.mInsetT = or.mInsetT; 
       r.mInsetR = or.mInsetR; 
       r.mInsetB = or.mInsetB; 
       r.mId = or.mId; 
      } 

      mHaveOpacity = orig.mHaveOpacity; 
      mOpacity = orig.mOpacity; 
      mHaveStateful = orig.mHaveStateful; 
      mStateful = orig.mStateful; 
      mCheckedConstantState = mCanConstantState = true; 
      } else { 
      mNum = 0; 
      mChildren = null; 
     } 
     } 

     @Override 
     public Drawable newDrawable() { 
     return new LayerDrawable(this, null); 
     } 

     @Override 
      public Drawable newDrawable(Resources res) { 
     return new LayerDrawable(this, res); 
      } 

      @Override 
     public int getChangingConfigurations() { 
     return mChangingConfigurations; 
     } 

     public final int getOpacity() { 
     if (mHaveOpacity) { 
      return mOpacity; 
     } 

     final int N = mNum; 
     int op = N > 0 ? mChildren[0].mDrawable.getOpacity() : PixelFormat.TRANSPARENT; 
     for (int i = 1; i < N; i++) { 
      op = Drawable.resolveOpacity(op, mChildren[i].mDrawable.getOpacity()); 
     } 
     mOpacity = op; 
     mHaveOpacity = true; 
     return op; 
     } 

     public final boolean isStateful() { 
     if (mHaveStateful) { 
      return mStateful; 
     } 

     boolean stateful = false; 
     final int N = mNum; 
     for (int i = 0; i < N; i++) { 
      if (mChildren[i].mDrawable.isStateful()) { 
       stateful = true; 
       break; 
      } 
     } 

     mStateful = stateful; 
     mHaveStateful = true; 
     return stateful; 
     } 

     public synchronized boolean canConstantState() { 
     if (!mCheckedConstantState && mChildren != null) { 
      mCanConstantState = true; 
      final int N = mNum; 
      for (int i=0; i<N; i++) { 
       if (mChildren[i].mDrawable.getConstantState() == null) { 
        mCanConstantState = false; 
        break; 
       } 
      } 
      mCheckedConstantState = true; 
     } 

     return mCanConstantState; 
     } 
     } 
     } 

我有这样的价值观/ attrs.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
<declare-styleable name="LayerDrawableItem"> 
<attr name="LayerDrawableItem_left" format="dimension" /> 
<attr name="LayerDrawableItem_top" format="dimension" /> 
<attr name="LayerDrawableItem_right" format="dimension" /> 
<attr name="LayerDrawableItem_bottom" format="dimension" /> 
<attr name="LayerDrawableItem_drawable" format="dimension" /> 
<attr name="LayerDrawableItem_id" format="dimension" /> 
</declare-styleable> 
</resources> 

回答

0

您需要添加一个mCallback成员。既然你是回调,或许mCallback真的是this

+0

是的,我宣布Drawable.Callback mCallback;在这之后,错误消失了,但我越来越接近力量 – 2012-02-15 06:43:08