ImageView setImageResource 无效,记一个bug

来源:互联网 发布:360搜索引擎怎么优化 编辑:程序博客网 时间:2024/05/22 16:48
package com.example.superdy.test;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Shader;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.support.annotation.ColorInt;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.TypedValue;import android.widget.ImageView;/** * A widget to display circular photo. */public class CircularPhotoView extends ImageView {    private int mBorderWidth;    private int mCanvasSize;    private Paint mPaint;    private Paint mPaintBorder;    private Paint mPaintBg;    private Paint mNotifyDotPaint;    private Paint mNotifyDotBorderPaint;    private Bitmap mBitmap;    private BitmapShader mShader;    private boolean mShowNotifyDot;    private float mNotifyDotRadius;    private float mNotifyDotBorderWidth;    public CircularPhotoView(final Context context) {        super(context);        init();    }    public CircularPhotoView(Context context, AttributeSet attrs) {        this(context, attrs, R.attr.circularImageViewStyle);    }    public CircularPhotoView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init();        // load the styled attributes and set their properties        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.Bibi_CircularImageView, defStyle, 0);        if (attributes.getBoolean(R.styleable.Bibi_CircularImageView_border, false)) {            int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics().density + 0.5f);            setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.Bibi_CircularImageView_border_width, defaultBorderSize));            setBorderColor(attributes.getColor(R.styleable.Bibi_CircularImageView_border_color, Color.WHITE));        }        if (attributes.getBoolean(R.styleable.Bibi_CircularImageView_shadow, false))            addShadow();        attributes.recycle();    }    private void init() {        // init paint        mPaint = new Paint();        mPaint.setAntiAlias(true);        mNotifyDotPaint = new Paint();        mNotifyDotPaint.setAntiAlias(true);        mNotifyDotPaint.setColor(getContext().getResources().getColor(R.color.bibi_call_log_miss_call_red_dot));        mNotifyDotBorderPaint = new Paint();        mNotifyDotBorderPaint.setAntiAlias(true);        mNotifyDotBorderPaint.setColor(getContext().getResources().getColor(R.color.bibi_application_bg));        DisplayMetrics dm = getResources().getDisplayMetrics();        mNotifyDotRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm);        mNotifyDotBorderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, dm);        mShowNotifyDot = false;    }    public void setShowNotifyDot(boolean showNotifyDot) {        mShowNotifyDot = showNotifyDot;    }    public void setBorderWidth(int borderWidth) {        this.mBorderWidth = borderWidth;    }    public void setBorderColor(int borderColor) {        mPaintBorder = new Paint();        mPaintBorder.setAntiAlias(true);        mBorderWidth = DisplayUtils.px2dp(getContext(), 1);        if (mPaintBorder != null) {            mPaintBorder.setColor(borderColor);        }    }    public void setBgColor(@ColorInt int bgColor) {        if (bgColor != 0) {            mPaintBg = new Paint();            mPaintBg.setAntiAlias(true);            if (mPaintBg != null) {                mPaintBg.setColor(bgColor);            }        } else {            mPaintBg = null;        }    }    public void addShadow() {        mPaintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);    }    public void addShadow(float dx, float dy, float radius, int shadowColor) {        if (mPaintBorder == null) {            mPaintBorder = new Paint();            mPaintBorder.setAntiAlias(true);        }        mPaintBorder.setShadowLayer(radius, dx, dy, shadowColor);    }    @Override    public void setImageDrawable(Drawable drawable) {        super.setImageDrawable(drawable);        mBitmap = drawableToBitmap(getDrawable());        if (mBitmap != null && mCanvasSize > 0) {            mShader = new BitmapShader(Bitmap.createScaledBitmap(mBitmap, mCanvasSize, mCanvasSize, false),                    Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);        }    }    @Override    public void setImageBitmap(Bitmap image) {        super.setImageBitmap(image);        mBitmap = drawableToBitmap(getDrawable());        if (mBitmap != null && mCanvasSize > 0) {            mShader = new BitmapShader(Bitmap.createScaledBitmap(mBitmap, mCanvasSize, mCanvasSize, false),                    Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);        }    }    @Override    public void onDraw(Canvas canvas) {        int radius = (mCanvasSize - (mBorderWidth * 2)) / 2;        float centerX = mCanvasSize / 2;        float centerY = mCanvasSize / 2;        if (mPaintBorder != null) {            canvas.drawCircle(centerX, centerY, radius + mBorderWidth, mPaintBorder);        }        if (mPaintBg != null) {            canvas.drawCircle(centerX, centerY, radius, mPaintBg);        }        if (mShader != null && getDrawable() != null) {            mPaint.setShader(mShader);            canvas.drawCircle(centerX, centerY, radius, mPaint);        }        if (mShowNotifyDot) {            float notifyDotCenterX = centerX + (float) (radius / Math.sqrt(2));            float notifyDotCenterY = centerY - (float) (radius / Math.sqrt(2));            canvas.drawCircle(notifyDotCenterX, notifyDotCenterY,                    mNotifyDotRadius + mNotifyDotBorderWidth, mNotifyDotBorderPaint);            canvas.drawCircle(notifyDotCenterX, notifyDotCenterY,                    mNotifyDotRadius, mNotifyDotPaint);        }    }    @SuppressLint("DrawAllocation")    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = measureWidth(widthMeasureSpec);        int height = measureHeight(heightMeasureSpec);        boolean sizeChanged = mCanvasSize != width;        mCanvasSize = width;        if (mBitmap != null && sizeChanged && width > 0) {            mShader = new BitmapShader(Bitmap.createScaledBitmap(mBitmap, mCanvasSize, mCanvasSize, false),                    Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);        }        setMeasuredDimension(width, height);    }    private int measureWidth(int measureSpec) {        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            // The parent has determined an exact size for the child.            result = specSize;        } else if (specMode == MeasureSpec.AT_MOST) {            // The child can be as large as it wants up to the specified size.            result = specSize;        } else {            // The parent has not imposed any constraint on the child.            result = mCanvasSize;        }        return result;    }    private int measureHeight(int measureSpecHeight) {        int result = 0;        int specMode = MeasureSpec.getMode(measureSpecHeight);        int specSize = MeasureSpec.getSize(measureSpecHeight);        if (specMode == MeasureSpec.EXACTLY) {            // We were told how big to be            result = specSize;        } else if (specMode == MeasureSpec.AT_MOST) {            // The child can be as large as it wants up to the specified size.            result = specSize;        } else {            // Measure the text (beware: ascent is a negative number)            result = mCanvasSize;        }        return result;    }    private Bitmap drawableToBitmap(Drawable drawable) {        if (drawable == null) {            return null;        } else if (drawable instanceof BitmapDrawable) {            return ((BitmapDrawable) drawable).getBitmap();        }        Bitmap bitmap = null;        if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);        } else {            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);        }        Canvas canvas = new Canvas(bitmap);        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());        drawable.draw(canvas);        return bitmap;    }}
一开始以为是ImageView 在哪个地方被重新设置值了,各种方法设置,
后来才发现,fuck,这个类的onDraw 方法被重写了,
并且重写之后也没有调用父类的onDraw方法。
在解这个bug的过程中发现,用glide 加载这个Image是可以的,
Glide.with(this).load(R.mipmap.ic_launcher).into(iv_main);

或许是因为Glide内部用的不是setImageResource方法,而是用的
setImageDrawable
或者
setImageBitmap
这两个方法吧,
这个bug困扰了我好几个小时,
因为一开始思路错了,
总以为这个ImageView在别的地方被别人重新set值了,
后来发现imageView.postDelay 了整整30秒,依然无效,
才发现是这个方法的问题
之前写这个类的人真是个坑货!!!