FileDocCategorySizeDatePackage
ImageView.javaAPI DocAndroid 1.5 API30475Wed May 06 22:41:56 BST 2009android.widget

ImageView

public class ImageView extends android.view.View
Displays an arbitrary image, such as an icon. The ImageView class can load images from various sources (such as resources or content providers), takes care of computing its measurement from the image so that it can be used in any layout manager, and provides various display options such as scaling and tinting.
attr
ref android.R.styleable#ImageView_adjustViewBounds
attr
ref android.R.styleable#ImageView_src
attr
ref android.R.styleable#ImageView_maxWidth
attr
ref android.R.styleable#ImageView_maxHeight
attr
ref android.R.styleable#ImageView_tint
attr
ref android.R.styleable#ImageView_scaleType
attr
ref android.R.styleable#ImageView_cropToPadding

Fields Summary
private android.net.Uri
mUri
private int
mResource
private android.graphics.Matrix
mMatrix
private ScaleType
mScaleType
private boolean
mHaveFrame
private boolean
mAdjustViewBounds
private int
mMaxWidth
private int
mMaxHeight
private android.graphics.ColorFilter
mColorFilter
private int
mAlpha
private int
mViewAlphaScale
private android.graphics.drawable.Drawable
mDrawable
private int[]
mState
private boolean
mMergeState
private int
mLevel
private int
mDrawableWidth
private int
mDrawableHeight
private android.graphics.Matrix
mDrawMatrix
private android.graphics.RectF
mTempSrc
private android.graphics.RectF
mTempDst
private boolean
mCropToPadding
private boolean
mBaselineAligned
private static final ScaleType[]
sScaleTypeArray
private static final Matrix.ScaleToFit[]
sS2FArray
Constructors Summary
public ImageView(android.content.Context context)


       
        super(context);
        initImageView();
    
public ImageView(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, 0);
    
public ImageView(android.content.Context context, android.util.AttributeSet attrs, int defStyle)

        super(context, attrs, defStyle);
        initImageView();

        TypedArray a = context.obtainStyledAttributes(attrs,
                com.android.internal.R.styleable.ImageView, defStyle, 0);

        Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
        if (d != null) {
            setImageDrawable(d);
        }

        mBaselineAligned = a.getBoolean(
                com.android.internal.R.styleable.ImageView_baselineAlignBottom, false);
        
        setAdjustViewBounds(
            a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds,
            false));

        setMaxWidth(a.getDimensionPixelSize(
                com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
        
        setMaxHeight(a.getDimensionPixelSize(
                com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
        
        int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1);
        if (index >= 0) {
            setScaleType(sScaleTypeArray[index]);
        }

        int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
        if (tint != 0) {
            setColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
        }
        
        mCropToPadding = a.getBoolean(
                com.android.internal.R.styleable.ImageView_cropToPadding, false);
        
        a.recycle();

        //need inflate syntax/reader for matrix
    
Methods Summary
private voidapplyColorMod()

        if (mDrawable != null) {
            mDrawable.setColorFilter(mColorFilter);
            mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8);
        }
    
public final voidclearColorFilter()

        setColorFilter(null);
    
private voidconfigureBounds()

        if (mDrawable == null || !mHaveFrame) {
            return;
        }

        int dwidth = mDrawableWidth;
        int dheight = mDrawableHeight;

        int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
        int vheight = getHeight() - mPaddingTop - mPaddingBottom;

        boolean fits = (dwidth < 0 || vwidth == dwidth) &&
                       (dheight < 0 || vheight == dheight);

        if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
            /* If the drawable has no intrinsic size, or we're told to
                scaletofit, then we just fill our entire view.
            */
            mDrawable.setBounds(0, 0, vwidth, vheight);
            mDrawMatrix = null;
        } else {
            // We need to do the scaling ourself, so have the drawable
            // use its native size.
            mDrawable.setBounds(0, 0, dwidth, dheight);

            if (ScaleType.MATRIX == mScaleType) {
                // Use the specified matrix as-is.
                if (mMatrix.isIdentity()) {
                    mDrawMatrix = null;
                } else {
                    mDrawMatrix = mMatrix;
                }
            } else if (fits) {
                // The bitmap fits exactly, no transform needed.
                mDrawMatrix = null;
            } else if (ScaleType.CENTER == mScaleType) {
                // Center bitmap in view, no scaling.
                mDrawMatrix = mMatrix;
                mDrawMatrix.setTranslate((vwidth - dwidth) * 0.5f,
                                         (vheight - dheight) * 0.5f);
            } else if (ScaleType.CENTER_CROP == mScaleType) {
                mDrawMatrix = mMatrix;

                float scale;
                float dx = 0, dy = 0;

                if (dwidth * vheight > vwidth * dheight) {
                    scale = (float) vheight / (float) dheight; 
                    dx = (vwidth - dwidth * scale) * 0.5f;
                } else {
                    scale = (float) vwidth / (float) dwidth;
                    dy = (vheight - dheight * scale) * 0.5f;
                }

                mDrawMatrix.setScale(scale, scale);
                mDrawMatrix.postTranslate(dx, dy);
            } else if (ScaleType.CENTER_INSIDE == mScaleType) {
                mDrawMatrix = mMatrix;
                float scale;
                float dx;
                float dy;
                
                if (dwidth <= vwidth && dheight <= vheight) {
                    scale = 1.0f;
                } else {
                    scale = Math.min((float) vwidth / (float) dwidth, 
                            (float) vheight / (float) dheight);
                }
                
                dx = (vwidth - dwidth * scale) * 0.5f;
                dy = (vheight - dheight * scale) * 0.5f;

                mDrawMatrix.setScale(scale, scale);
                mDrawMatrix.postTranslate(dx, dy);
            } else {
                // Generate the required transform.
                mTempSrc.set(0, 0, dwidth, dheight);
                mTempDst.set(0, 0, vwidth, vheight);
                
                mDrawMatrix = mMatrix;
                mDrawMatrix.setRectToRect(mTempSrc, mTempDst,
                                          scaleTypeToScaleToFit(mScaleType));
            }
        }
    
protected voiddrawableStateChanged()

        super.drawableStateChanged();
        Drawable d = mDrawable;
        if (d != null && d.isStateful()) {
            d.setState(getDrawableState());
        }
    
public intgetBaseline()

        return mBaselineAligned ? getMeasuredHeight() : -1;
    
public android.graphics.drawable.DrawablegetDrawable()
Return the view's drawable, or null if no drawable has been assigned.

        return mDrawable;
    
public android.graphics.MatrixgetImageMatrix()
Return the view's optional matrix. This is applied to the view's drawable when it is drawn. If there is not matrix, this method will return null. Do not change this matrix in place. If you want a different matrix applied to the drawable, be sure to call setImageMatrix().

        return mMatrix;
    
public android.widget.ImageView$ScaleTypegetScaleType()
Return the current scale type in use by this ImageView.

see
ImageView.ScaleType
attr
ref android.R.styleable#ImageView_scaleType

        return mScaleType;
    
private voidinitImageView()

        mMatrix     = new Matrix();
        mScaleType  = ScaleType.FIT_CENTER;
    
public voidinvalidateDrawable(android.graphics.drawable.Drawable dr)

        if (dr == mDrawable) {
            /* we invalidate the whole view in this case because it's very
             * hard to know where the drawable actually is. This is made
             * complicated because of the offsets and transformations that
             * can be applied. In theory we could get the drawable's bounds
             * and run them through the transformation and offsets, but this
             * is probably not worth the effort.
             */
            invalidate();
        } else {
            super.invalidateDrawable(dr);
        }
    
public int[]onCreateDrawableState(int extraSpace)

        if (mState == null) {
            return super.onCreateDrawableState(extraSpace);
        } else if (!mMergeState) {
            return mState;
        } else {
            return mergeDrawableStates(
                    super.onCreateDrawableState(extraSpace + mState.length), mState);
        }
    
protected voidonDraw(android.graphics.Canvas canvas)

        super.onDraw(canvas);

        if (mDrawable == null) {
            return; // couldn't resolve the URI
        }

        if (mDrawableWidth == 0 || mDrawableHeight == 0) {
            return;     // nothing to draw (empty bounds)
        }

        if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
            mDrawable.draw(canvas);
        } else {
            int saveCount = canvas.getSaveCount();
            canvas.save();
            
            if (mCropToPadding) {
                final int scrollX = mScrollX;
                final int scrollY = mScrollY;
                canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
                        scrollX + mRight - mLeft - mPaddingRight,
                        scrollY + mBottom - mTop - mPaddingBottom);
            }
            
            canvas.translate(mPaddingLeft, mPaddingTop);

            if (mDrawMatrix != null) {
                canvas.concat(mDrawMatrix);
            }
            mDrawable.draw(canvas);
            canvas.restoreToCount(saveCount);
        }
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        resolveUri();
        int w;
        int h;
        
        // Desired aspect ratio of the view's contents (not including padding)
        float desiredAspect = 0.0f;
        
        // We are allowed to change the view's width
        boolean resizeWidth = false;
        
        // We are allowed to change the view's height
        boolean resizeHeight = false;
        
        if (mDrawable == null) {
            // If no drawable, its intrinsic size is 0.
            mDrawableWidth = -1;
            mDrawableHeight = -1;
            w = h = 0;
        } else {
            w = mDrawableWidth;
            h = mDrawableHeight;
            if (w <= 0) w = 1;
            if (h <= 0) h = 1;
            
            // We are supposed to adjust view bounds to match the aspect
            // ratio of our drawable. See if that is possible.
            if (mAdjustViewBounds) {
                
                int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
                int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
                
                resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
                resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
                
                desiredAspect = (float)w/(float)h;
            }
        }
        
        int pleft = mPaddingLeft;
        int pright = mPaddingRight;
        int ptop = mPaddingTop;
        int pbottom = mPaddingBottom;

        int widthSize;
        int heightSize;

        if (resizeWidth || resizeHeight) {
            /* If we get here, it means we want to resize to match the
                drawables aspect ratio, and we have the freedom to change at
                least one dimension. 
            */

            // Get the max possible width given our constraints
            widthSize = resolveAdjustedSize(w + pleft + pright,
                                                 mMaxWidth, widthMeasureSpec);
            
            // Get the max possible height given our constraints
            heightSize = resolveAdjustedSize(h + ptop + pbottom,
                                                mMaxHeight, heightMeasureSpec);
            
            if (desiredAspect != 0.0f) {
                // See what our actual aspect ratio is
                float actualAspect = (float)(widthSize - pleft - pright) /
                                        (heightSize - ptop - pbottom);
                
                if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {
                    
                    boolean done = false;
                    
                    // Try adjusting width to be proportional to height
                    if (resizeWidth) {
                        int newWidth = (int)(desiredAspect *
                                            (heightSize - ptop - pbottom))
                                            + pleft + pright;
                        if (newWidth <= widthSize) {
                            widthSize = newWidth;
                            done = true;
                        } 
                    }
                    
                    // Try adjusting height to be proportional to width
                    if (!done && resizeHeight) {
                        int newHeight = (int)((widthSize - pleft - pright)
                                            / desiredAspect) + ptop + pbottom;
                        if (newHeight <= heightSize) {
                            heightSize = newHeight;
                        } 
                    }
                }
            }
        } else {
            /* We are either don't want to preserve the drawables aspect ratio,
               or we are not allowed to change view dimensions. Just measure in
               the normal way.
            */
            w += pleft + pright;
            h += ptop + pbottom;
                
            w = Math.max(w, getSuggestedMinimumWidth());
            h = Math.max(h, getSuggestedMinimumHeight());

            widthSize = resolveSize(w, widthMeasureSpec);
            heightSize = resolveSize(h, heightMeasureSpec);
        }

        setMeasuredDimension(widthSize, heightSize);
    
protected booleanonSetAlpha(int alpha)

        if (getBackground() == null) {
            int scale = alpha + (alpha >> 7);
            if (mViewAlphaScale != scale) {
                mViewAlphaScale = scale;
                applyColorMod();
            }
            return true;
        }
        return false;
    
private voidresizeFromDrawable()

        Drawable d = mDrawable;
        if (d != null) {
            int w = d.getIntrinsicWidth();
            if (w < 0) w = mDrawableWidth;
            int h = d.getIntrinsicHeight();
            if (h < 0) h = mDrawableHeight;
            if (w != mDrawableWidth || h != mDrawableHeight) {
                mDrawableWidth = w;
                mDrawableHeight = h;
                requestLayout();
            }
        }
    
private intresolveAdjustedSize(int desiredSize, int maxSize, int measureSpec)

        int result = desiredSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize =  MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                /* Parent says we can be as big as we want. Just don't be larger
                   than max size imposed on ourselves.
                */
                result = Math.min(desiredSize, maxSize);
                break;
            case MeasureSpec.AT_MOST:
                // Parent says we can be as big as we want, up to specSize. 
                // Don't be larger than specSize, and don't be larger than 
                // the max size imposed on ourselves.
                result = Math.min(Math.min(desiredSize, specSize), maxSize);
                break;
            case MeasureSpec.EXACTLY:
                // No choice. Do what we are told.
                result = specSize;
                break;
        }
        return result;
    
private voidresolveUri()

        if (mDrawable != null) {
            return;
        }

        Resources rsrc = getResources();
        if (rsrc == null) {
            return;
        }

        Drawable d = null;

        if (mResource != 0) {
            try {
                d = rsrc.getDrawable(mResource);
            } catch (Exception e) {
                Log.w("ImageView", "Unable to find resource: " + mResource, e);
                // Don't try again.
                mUri = null;
            }
        } else if (mUri != null) {
            if ("content".equals(mUri.getScheme())) {
                try {
                    d = Drawable.createFromStream(
                        mContext.getContentResolver().openInputStream(mUri),
                        null);
                } catch (Exception e) {
                    Log.w("ImageView", "Unable to open content: " + mUri, e);
                }
            } else {
                d = Drawable.createFromPath(mUri.toString());
            }
    
            if (d == null) {
                System.out.println("resolveUri failed on bad bitmap uri: "
                                   + mUri);
                // Don't try again.
                mUri = null;
            }
        } else {
            return;
        }

        updateDrawable(d);
    
private static Matrix.ScaleToFitscaleTypeToScaleToFit(android.widget.ImageView$ScaleType st)


          
        // ScaleToFit enum to their corresponding Matrix.ScaleToFit values
        return sS2FArray[st.nativeInt - 1];
    
public voidsetAdjustViewBounds(boolean adjustViewBounds)
Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable.

param
adjustViewBounds Whether to adjust the bounds of this view to presrve the original aspect ratio of the drawable
attr
ref android.R.styleable#ImageView_adjustViewBounds

        mAdjustViewBounds = adjustViewBounds;
        if (adjustViewBounds) {
            setScaleType(ScaleType.FIT_CENTER);
        }
    
public voidsetAlpha(int alpha)

        alpha &= 0xFF;          // keep it legal
        if (mAlpha != alpha) {
            mAlpha = alpha;
            applyColorMod();
            invalidate();
        }
    
public final voidsetColorFilter(int color, PorterDuff.Mode mode)
Set a tinting option for the image.

param
color Color tint to apply.
param
mode How to apply the color. The standard mode is {@link PorterDuff.Mode#SRC_ATOP}
attr
ref android.R.styleable#ImageView_tint

        setColorFilter(new PorterDuffColorFilter(color, mode));
    
public voidsetColorFilter(android.graphics.ColorFilter cf)
Apply an arbitrary colorfilter to the image.

param
cf the colorfilter to apply (may be null)

        if (mColorFilter != cf) {
            mColorFilter = cf;
            applyColorMod();
            invalidate();
        }
    
protected booleansetFrame(int l, int t, int r, int b)

        boolean changed = super.setFrame(l, t, r, b);
        mHaveFrame = true;
        configureBounds();
        return changed;
    
public voidsetImageBitmap(android.graphics.Bitmap bm)
Sets a Bitmap as the content of this ImageView.

param
bm The bitmap to set

        // if this is used frequently, may handle bitmaps explicitly
        // to reduce the intermediate drawable object
        setImageDrawable(new BitmapDrawable(bm));
    
public voidsetImageDrawable(android.graphics.drawable.Drawable drawable)
Sets a drawable as the content of this ImageView.

param
drawable The drawable to set

        if (mDrawable != drawable) {
            mResource = 0;
            mUri = null;
            updateDrawable(drawable);
            requestLayout();
            invalidate();
        }
    
public voidsetImageLevel(int level)
Sets the image level, when it is constructed from a {@link android.graphics.drawable.LevelListDrawable}.

param
level The new level for the image.

        mLevel = level;
        if (mDrawable != null) {
            mDrawable.setLevel(level);
            resizeFromDrawable();
        }
    
public voidsetImageMatrix(android.graphics.Matrix matrix)

        // collaps null and identity to just null
        if (matrix != null && matrix.isIdentity()) {
            matrix = null;
        }
        
        // don't invalidate unless we're actually changing our matrix
        if (matrix == null && !mMatrix.isIdentity() ||
                matrix != null && !mMatrix.equals(matrix)) {
            mMatrix.set(matrix);
            invalidate();
        }
    
public voidsetImageResource(int resId)
Sets a drawable as the content of this ImageView.

param
resId the resource identifier of the the drawable
attr
ref android.R.styleable#ImageView_src

        if (mUri != null || mResource != resId) {
            updateDrawable(null);
            mResource = resId;
            mUri = null;
            resolveUri();
            requestLayout();
            invalidate();
        }
    
public voidsetImageState(int[] state, boolean merge)

        mState = state;
        mMergeState = merge;
        if (mDrawable != null) {
            refreshDrawableState();
            resizeFromDrawable();
        }
    
public voidsetImageURI(android.net.Uri uri)
Sets the content of this ImageView to the specified Uri.

param
uri The Uri of an image

        if (mResource != 0 ||
                (mUri != uri &&
                 (uri == null || mUri == null || !uri.equals(mUri)))) {
            updateDrawable(null);
            mResource = 0;
            mUri = uri;
            resolveUri();
            requestLayout();
            invalidate();
        }
    
public voidsetMaxHeight(int maxHeight)
An optional argument to supply a maximum height for this view. Only valid if {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to WRAP_CONTENT.

Note that this view could be still smaller than 100 x 100 using this approach if the original image is small. To set an image to a fixed size, specify that size in the layout params and then use {@link #setScaleType} to determine how to fit the image within the bounds.

param
maxHeight maximum height for this view
attr
ref android.R.styleable#ImageView_maxHeight

        mMaxHeight = maxHeight;
    
public voidsetMaxWidth(int maxWidth)
An optional argument to supply a maximum width for this view. Only valid if {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to WRAP_CONTENT.

Note that this view could be still smaller than 100 x 100 using this approach if the original image is small. To set an image to a fixed size, specify that size in the layout params and then use {@link #setScaleType} to determine how to fit the image within the bounds.

param
maxWidth maximum width for this view
attr
ref android.R.styleable#ImageView_maxWidth

        mMaxWidth = maxWidth;
    
public voidsetScaleType(android.widget.ImageView$ScaleType scaleType)
Controls how the image should be resized or moved to match the size of this ImageView.

param
scaleType The desired scaling mode.
attr
ref android.R.styleable#ImageView_scaleType

        if (scaleType == null) {
            throw new NullPointerException();
        }

        if (mScaleType != scaleType) {
            mScaleType = scaleType;

            setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);            

            requestLayout();
            invalidate();
        }
    
public voidsetSelected(boolean selected)

        super.setSelected(selected);
        resizeFromDrawable();
    
private voidupdateDrawable(android.graphics.drawable.Drawable d)

        if (mDrawable != null) {
            mDrawable.setCallback(null);
            unscheduleDrawable(mDrawable);
        }
        mDrawable = d;
        if (d != null) {
            d.setCallback(this);
            if (d.isStateful()) {
                d.setState(getDrawableState());
            }
            d.setLevel(mLevel);
            mDrawableWidth = d.getIntrinsicWidth();
            mDrawableHeight = d.getIntrinsicHeight();
            applyColorMod();
            configureBounds();
        }
    
protected booleanverifyDrawable(android.graphics.drawable.Drawable dr)

        return mDrawable == dr || super.verifyDrawable(dr);