有人可以帮我解决此代码中mcallback中的错误

时间:2012-02-15 05:29:14

标签: android layer

这是实现图层概念的代码。即动态添加图层。我在//中覆盖了来自Drawable.callback的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;
         }
        }
        }

我在values / 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>

1 个答案:

答案 0 :(得分:0)

您需要添加mCallback成员。由于您是回调,因此mCallback可能是this