Android 自定义Imageview的点击效果

/**
 * 扩展的{@link ImageView}, 增加了多种点击效果.

 * 效果请参照{@link ButtonEffect}
 *
 */
public class UIImageButton extends ImageView {

    private static final int EFFECT_NONE = 0;

    /** 光照效果 **/
    private static final int EFFECT_SUN = 1;

    /** 变暗效果 **/
    private static final int EFFECT_DARKEN = 2;

    /** 描边效果 **/
    private static final int EFFECT_RIM = 3;

    /** 水印效果 **/
    private static final int EFFECT_WATERMARK = 4;

    /** 效果 **/
    // private int mEffect = EFFECT_SUN;
    private ButtonEffect mEffect = ButtonEffect.SUNSHINE;

    /** 是否开启效果 **/
    private boolean fEffect = false;

    /** 水印 **/
    private Drawable mWatermark;

    /** 默认画笔 **/
    private Paint mPaint;

    /** 效果集, 效果不可进行叠加 **/
    public enum ButtonEffect {

        /** 无效果,设置该属性后,使用时请参照{@link ImageView} **/
        NONE(EFFECT_NONE),

        /** 该属性会产生光照的效果 **/
        SUNSHINE(EFFECT_SUN),

        /** 该属性会产生变暗的效果 **/
        DARKEN(EFFECT_DARKEN),

        /** 该属性会产生描边的效果 **/
        RIM(EFFECT_RIM),

        /** 该属性为水印效果,设置该属性还需要同时设置水印来源{@link #mWatermark} **/
        WATERMARK(EFFECT_WATERMARK);

        private ButtonEffect(int nativeInt) {
            this.nativeInt = nativeInt;
        }

        final int nativeInt;
    }
    

    public UIImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.UIImageButton, defStyle, 0);

        if (a != null) {
            mWatermark = a
                    .getDrawable(R.styleable.UIImageButton_ui_image_button_mark_src);

            final int effect = a.getInteger(
                    R.styleable.UIImageButton_ui_image_button_type,
                    ButtonEffect.NONE.nativeInt);

            if (effect == ButtonEffect.NONE.nativeInt) {
                mEffect = ButtonEffect.NONE;
            } else if (effect == ButtonEffect.SUNSHINE.nativeInt) {
                mEffect = ButtonEffect.SUNSHINE;
            } else if (effect == ButtonEffect.DARKEN.nativeInt) {
                mEffect = ButtonEffect.DARKEN;
            } else if (effect == ButtonEffect.RIM.nativeInt) {
                mEffect = ButtonEffect.RIM;
            } else if (effect == ButtonEffect.WATERMARK.nativeInt) {
                mEffect = ButtonEffect.WATERMARK;
            }

            a.recycle();
        }
    }
    
    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        
//        boolean reset = true;
//        
//        for(int i : getDrawableState()){
//            if(i == android.R.attr.state_pressed){
//                reset = false;
//                break;
//            }
//        }
//        
//        if(reset){
//            invalidEffect();
//            invalidate();
//        }
    }


    public UIImageButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public UIImageButton(Context context) {
        this(context, null);
    }

    private void init() {
        setClickable(true);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setFilterBitmap(true);
    }

    /**
     * 设置特效类型
     *
     * @param effect
     */
    public void setEffectType(ButtonEffect effect) {
        mEffect = effect;
        invalidate();
    }

    /**
     * 获得特效类型
     *
     * @return
     */
    public ButtonEffect getEffectType() {
        return mEffect;
    }

    /**
     * 设置水印
     *
     * @param bmp
     *            水印
     **/
    public void setWaterMask(Bitmap bmp) {
        setWaterMask(new BitmapDrawable(getContext().getResources(), bmp));
    }

    /**
     * 设置水印
     *
     * @param ResourceId
     *            水印资源
     **/
    public void setWaterMask(int ResourceId) {
        setWaterMask(getResources().getDrawable(ResourceId));
    }

    /**
     * 设置水印
     *
     * @param drawable
     *            水印
     **/
    public void setWaterMask(Drawable drawable) {
        this.mWatermark = drawable;
        invalidate();
    }
    
    /**
     *  使效果失效
     */
    public void invalidEffect(){
        fEffect = false;
        
        if (mEffect == ButtonEffect.DARKEN) {
            setColorFilter(getColorFilter(effectDarken(1.0f)));
        }
        
        invalidate();
    }
    
    /**
     * 使效果生效
     */
    protected void validEffect(){
        
        fEffect = true;
        
        if (mEffect == ButtonEffect.DARKEN) {
            setColorFilter(getColorFilter(effectDarken(0.8f)));
        }
        
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);
        
        if(getDrawable() == null ){
            return;
        }
        

        if (fEffect && mEffect == ButtonEffect.NONE) {
//            return;
            final Drawable d = getDrawable();
            final Bitmap bmp = Bitmap.createBitmap(d.getIntrinsicWidth(),
                    d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            final Drawable nul = getContext().getResources().getDrawable(R.drawable.bg_null);
            Log.i("size", nul.getIntrinsicWidth()+"     "+nul.getIntrinsicHeight());
            BitmapDrawable bd = (BitmapDrawable) nul;

            Bitmap bmp_null = bd.getBitmap();
                    
//            final Canvas c = new Canvas(bmp_null);
//            nul.draw(c);
            canvas.drawBitmap(bmp_null, 0, 0, mPaint);
//            canvas.drawBitmap(bmp, bmp.getWidth() / 2, bmp.getHeight() / 2, mPaint);
//            mPaint.setColor(getContext().getResources().getColor(R.color.default_navigationbar_text_color));
//            canvas.drawLine(0, 0, 30, 5, mPaint);
        } else if (fEffect && mEffect == ButtonEffect.SUNSHINE) {

            final Drawable d = getDrawable();
            final Bitmap bmp = Bitmap.createBitmap(d.getIntrinsicWidth(),
                    d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            final Canvas c = new Canvas(bmp);
            d.draw(c);

            canvas.drawBitmap(
                    effectSunshine(bmp, bmp.getWidth() / 2, bmp.getHeight() / 2),
                    0, 0, mPaint);

        } else if (mWatermark != null && fEffect
                && mEffect == ButtonEffect.WATERMARK) {

            final Drawable d = getDrawable();
            final int left = (d.getIntrinsicWidth() - mWatermark
                    .getIntrinsicWidth()) / 2;
            final int top = (d.getIntrinsicHeight() - mWatermark
                    .getIntrinsicHeight()) / 2;
            // canvas.drawBitmap(mWatermark, left, top, mPaint);
            mWatermark.setBounds(left, top,
                    left + mWatermark.getIntrinsicWidth(),
                    top + mWatermark.getIntrinsicHeight());
            mWatermark.draw(canvas);

        } else if (fEffect && mEffect == ButtonEffect.RIM) {

            final Drawable d = getDrawable();
            final Bitmap bmp = Bitmap.createBitmap(d.getIntrinsicWidth(),
                    d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);

            final Canvas c = new Canvas(bmp);
            d.draw(c);

            canvas.drawBitmap(effectRim(bmp), 0, 0, mPaint);
        }
    }
    
    @Override
    public boolean onTrackballEvent(MotionEvent event) {
        return super.onTrackballEvent(event);
    }
    

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        final int action = MotionEventCompat.getActionMasked(event);
        
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            
            //不让父控件获取手势
//            if (getParent() != null) {
//                getParent().requestDisallowInterceptTouchEvent(true);
//            }
            validEffect();
            
            break;
            
        case MotionEvent.ACTION_MOVE:
//            if(!fEffect){
//                validEffect();
//            }
            break;
        case MotionEvent.ACTION_UP:
            
            //不让父控件获取手势
//            if (getParent() != null) {
//                getParent().requestDisallowInterceptTouchEvent(false);
//            }
            
            invalidEffect();
            
            break;
        case MotionEvent.ACTION_OUTSIDE:
            invalidEffect();
            break;
            
//        case MotionEvent.ACTION_CANCEL:
//            invalidEffect();
//            break;
        }

        return super.onTouchEvent(event);
    }

    /**
     * 光照效果
     *
     * @param bmp
     *            光照中心x坐标
     * @param centerX
     *            光照中心要坐标
     * @param centerY
     * @return
     */
    public static Bitmap effectSunshine(Bitmap bmp, int centerX, int centerY) {
        final int width = bmp.getWidth();
        final int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                Bitmap.Config.ARGB_8888);

        int pixR = 0;
        int pixG = 0;
        int pixB = 0;

        int pixColor = 0;

        int newR = 0;
        int newG = 0;
        int newB = 0;
        int radius = Math.min(centerX, centerY);

        final float strength = 150F; // 光照强度 100~150
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        int pos = 0;
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                pos = i * width + k;
                pixColor = pixels[pos];

                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);

                newR = pixR;
                newG = pixG;
                newB = pixB;

                // 计算当前点到光照中心的距离,平面座标系中求两点之间的距离
                int distance = (int) (Math.pow((centerY - i), 2) + Math.pow(
                        centerX - k, 2));
                if (distance < radius * radius) {
                    // 按照距离大小计算增加的光照值
                    int result = (int) (strength * (1.0 - Math.sqrt(distance)
                            / radius));
                    newR = pixR + result;
                    newG = pixG + result;
                    newB = pixB + result;
                }

                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));

                pixels[pos] = Color.argb(Color.alpha(pixColor), newR, newG,
                        newB);

            }
        }

        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 调整亮度

     * 1f为原始亮度, 范围为0f - 2f
     */
    private ColorMatrix effectDarken(float light) {

        final ColorMatrix cm = new ColorMatrix();

        cm.setScale(light, light, light, 1);

        return cm;
    }

    private ColorMatrixColorFilter getColorFilter(ColorMatrix cm) {
        return new ColorMatrixColorFilter(cm);
    }

    /**
     * 缩放位图
     *
     * @param src
     *            原图
     * @param sx
     *            x缩放值
     * @param sy
     *            y缩放值
     * @return
     */
    private Bitmap scale(Bitmap src, float sx, float sy) {

        final Matrix m = new Matrix();

        m.postScale(sx, sy);

        return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(),
                m, true);
    }

    /**
     * 描边效果
     *
     * @param bmp
     * @return
     */
    private Bitmap effectRim(Bitmap bmp) {

        final Canvas c = new Canvas(bmp);

        final Bitmap rim = bmp.extractAlpha();
        final float sx = (rim.getWidth() - 5.0f) / rim.getWidth();
        final float sy = (rim.getHeight() - 5.0f) / rim.getHeight();
        final Bitmap scale = scale(rim, sx, sy);

        final Paint paint = new Paint();
        paint.setAntiAlias(true);

        paint.setColor(Color.CYAN);
        c.drawBitmap(rim, 0, 0, paint);

        final Bitmap b = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),
                Bitmap.Config.ARGB_8888);

        c.setBitmap(b);
        c.drawBitmap(scale, (b.getWidth() - scale.getWidth()) / 2,
                (b.getHeight() - scale.getHeight()) / 2, paint);

        final int[] pixels = new int[b.getWidth() * b.getHeight()];
        b.getPixels(pixels, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight());

        // 过滤掉遮罩部分
        for (int i = 0, m = bmp.getWidth(); i < m; i++) {
            for (int j = 0, n = bmp.getHeight(); j < n; j++) {

                final int pos = i * bmp.getWidth() + j;

                if (pixels[pos] == Color.CYAN) {
                    bmp.setPixel(i, j, Color.TRANSPARENT);
                }
            }
        }

        return bmp;
    }
}

你可能感兴趣的:(Android 自定义Imageview的点击效果)