Android自定义View——可在背景图和前景图显示遮罩效果的ImageView

来源:互联网 发布:mysql 连接远程数据库 编辑:程序博客网 时间:2024/04/30 06:59
如果对android自定义view还不太属性,可以查看我之前写的文章《Android自定义View——基础知识篇

废话不多说,先上效果图


从图中可以看出,我们可以设置背景图或前景图的遮罩,而且遮罩范围可以设置为整张图片或非透明部分,另外,还可以设置遮罩的颜色。

实现的难点在于,遮罩范围可以设置为整张图片或非透明部分:
.遮罩范围为整张图片时,直接通过canvas.drawColor(),在图片上面绘制一层遮罩。
.遮罩为非透明部分时,则通过drawable.setColorFilter(),设置drawable对象的颜色滤镜。原理如下:
 
// 创建新的颜色矩阵      ColorMatrix colorMatrix = new ColorMatrix(new float[]{         a,b,c,d,e,         f,g,h,i,j,         k,l,m,n,o,         p,q,r,s,t});      // 已知一个颜色值ARGB,则经过下面的矩阵运算可得出新的颜色值     /* int red   = a*R + b*R + c*R + d*R + e;         int green = f*G + g*G + h*G + i*G + j;         int blue  = k*B + l*B + m*B + n*B + o;         int alpha = p*A + q*A + r*A + s*A + t;      */      // 设置图片滤镜      getDrawable().setColorFilter(new ColorMatrixColorFilter(colorMatrix));      绘图      drawable.draw(canvas)

(要更深入了解图像颜色处理,可以查看这篇文章:http://www.cnblogs.com/menlsh/archive/2013/02/03/2890888.html

关键代码:
/** * 可在背景图和前景图显示遮罩效果的ImageView (前提设置了setClickable(true)) * * @author huangziwei *  */public class MaskImageView extends ImageView {    // 遮罩的范围    public static final int MASK_LEVEL_BACKGROUND = 1; // 背景图显示遮罩    public static final int MASK_LEVEL_FOREGROUND = 2; // 前景图显示遮罩    private boolean mIsIgnoreAlpha = true; // 是否忽略图片的透明度,默认为true,透明部分不显示遮罩    private boolean mIsShowMaskOnClick = true; // 点击时是否显示遮罩,默认开启    private int mShadeColor = 0x00ffffff; // 遮罩颜色(argb,需要设置透明度)    private int mMaskLevel = MASK_LEVEL_FOREGROUND; // 默认为前景图显示遮罩    ColorMatrix mColorMatrix = new ColorMatrix(); // 颜色矩阵    ColorFilter mColorFilter;    public MaskImageView(Context context) {        this(context, null);    }    public MaskImageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MaskImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(attrs);    }    private void init(AttributeSet attrs) {        TypedArray a = getContext().obtainStyledAttributes(attrs,                R.styleable.MaskImageView);        mIsIgnoreAlpha = a.getBoolean(R.styleable.MaskImageView_is_ignore_alpha, mIsIgnoreAlpha);        mIsShowMaskOnClick = a.getBoolean(R.styleable.MaskImageView_is_show_mask_on_click, mIsShowMaskOnClick);        mShadeColor = a.getColor(R.styleable.MaskImageView_mask_color, mShadeColor);        mMaskLevel = a.getInt(R.styleable.MaskImageView_mask_level, mMaskLevel);        // 忽略透明度时的颜色矩阵        float r = Color.alpha(mShadeColor) / 255f;        r=r-(1 - r)*0.15f;        float rr = (1 - r)*1.15f;        setColorMatrix(new float[]{                rr, 0, 0, 0, Color.red(mShadeColor) * r,                0, rr, 0, 0, Color.green(mShadeColor) * r,                0, 0, rr, 0, Color.blue(mShadeColor) * r,                0, 0, 0, 1, 0,        });        a.recycle();    }    private void setColorMatrix(float[] matrix) {        mColorMatrix.set(matrix);        mColorFilter = new ColorMatrixColorFilter(mColorMatrix);    }    // all drawables instances loaded from  the same resource share a common state    // 从同一个资源文件获取的drawable对象共享一个状态信息,为了避免修改其中一个drawable导致其他drawable被影响,需要调用mutate()    // 因为背景图在draw()阶段绘制,所以修改了背景图状态后必须调用invalidateSelf()刷新    private void setDrawableColorFilter(ColorFilter colorFilter) {        if (mMaskLevel == MASK_LEVEL_BACKGROUND) {            if (getBackground() != null) {                getBackground().mutate();                getBackground().setColorFilter(colorFilter);                getBackground().invalidateSelf();            }        } else if (mMaskLevel == MASK_LEVEL_FOREGROUND) {            if (getDrawable() != null) {                getDrawable().mutate();                getDrawable().setColorFilter(colorFilter);                getDrawable().invalidateSelf();            }        }    }    @Override    protected void onDraw(Canvas canvas) {        if (mIsIgnoreAlpha) { // 忽略透明度            if (mIsShowMaskOnClick && isPressed()) {                // 绘制遮罩层                setDrawableColorFilter(mColorFilter);            } else {                setDrawableColorFilter(null);            }            super.onDraw(canvas);        } else { // 不忽略透明度            setDrawableColorFilter(null);            if (mMaskLevel == MASK_LEVEL_BACKGROUND) { // 背景图                if (mIsShowMaskOnClick && isPressed()) {                    // 绘制遮罩层                    canvas.drawColor(mShadeColor);                }                super.onDraw(canvas);            } else { // 前景图                super.onDraw(canvas);                if (mIsShowMaskOnClick && isPressed()) {                    // 绘制遮罩层                    canvas.drawColor(mShadeColor);                }            }        }    }    /**     * view状态改变     */    @Override    protected void drawableStateChanged(){        super.drawableStateChanged();        invalidate();    }    public boolean isIsIgnoreAlpha() {        return mIsIgnoreAlpha;    }    public void setIsIgnoreAlpha(boolean mIsIgnoreAlpha) {        this.mIsIgnoreAlpha = mIsIgnoreAlpha;        invalidate();    }    public boolean isIsShowMaskOnClick() {        return mIsShowMaskOnClick;    }    public void setIsShowMaskOnClick(boolean mIsShowMaskOnClick) {        this.mIsShowMaskOnClick = mIsShowMaskOnClick;        invalidate();    }    public int getShadeColor() {        return mShadeColor;    }    public void setShadeColor(int mShadeColor) {        this.mShadeColor = mShadeColor;        // 忽略透明度时的颜色矩阵        float r = Color.alpha(mShadeColor) / 255f;        r=r-(1 - r)*0.15f;        float rr = (1 - r)*1.15f;        setColorMatrix(new float[]{                rr, 0, 0, 0, Color.red(mShadeColor) * r,                0, rr, 0, 0, Color.green(mShadeColor) * r,                0, 0, rr, 0, Color.blue(mShadeColor) * r,                0, 0, 0, 1, 0,        });        invalidate();    }    public int getMaskLevel() {        return mMaskLevel;    }    public void setMaskLevel(int mMaskLevel) {        this.mMaskLevel = mMaskLevel;        invalidate();    }}

// res/values/attrs.xml<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MaskImageView">        <attr name="mask_level" format="enum">            <enum name="background" value="1"/>            <enum name="foreground" value="2"/>        </attr>        <!-- 设置了setClickable(true)才生效,默认开启遮罩-->        <attr name="is_show_mask_on_click" format="boolean"/>        <attr name="mask_color" format="color"/>        <!--是否忽略图片的透明度,默认为true,透明部分不显示遮罩 -->        <attr name="is_ignore_alpha" format="boolean"/>    </declare-styleable></resources>


关于自定义样式,可以查看上篇文章《Android自定义View——自定义样式》。

相关代码我放在了github上:https://github.com/1993hzw/Androids , 接下来的项目代码我都会放在上面,争取做一个类型工具的库。
0 0
原创粉丝点击