上下扫描以及扩散扫描

来源:互联网 发布:柳州市一职校淘宝地址 编辑:程序博客网 时间:2024/06/05 17:14

效果图


思路

        显示图片,所以继承ImageView。

        图片有两种状态:一种是正常状态,一种是有较暗状态。较暗状态是将按一定的透明度比例绘制正常的图片即可。

代码

public class DakaImageView extends ImageView {    /**     * 从上往下刷新     */    private static final int ANIM_UP_DOWN = 1;    /**     * 波纹扩散     */    private static final int ANIM_SPREAD = 2;    /**     * 没有动画执行     */    private static final int ANIM_NO = 3;    private static final String TAG = DakaImageView.class.getSimpleName();    private int mCurrAnim = ANIM_NO;    private ValueAnimator mUpdownAnim, mSpreadAnim;    private Paint mUpdownPaint;    private float mMaskOffsetY = 0, mMaskoffsetRadius = 0;    private Bitmap mUpdownMaskBitmap, mSpreadMaskBitmap, mUnmaskBitmap;    private static final float ALPHA = 0.3f;    private Path path;    public DakaImageView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    private void init() {        setLayerType(LAYER_TYPE_SOFTWARE, null);        mUpdownPaint = new Paint();        mUpdownPaint.setAntiAlias(true);        mUpdownPaint.setStyle(Paint.Style.FILL);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //设置死宽高        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width = MeasureSpec.makeMeasureSpec(getDrawable().getIntrinsicWidth(),MeasureSpec.EXACTLY);        int height = MeasureSpec.makeMeasureSpec(getDrawable().getIntrinsicHeight(),MeasureSpec.EXACTLY);        setMeasuredDimension(width,height);    }    @Override    protected void onDetachedFromWindow() { //回收相应的资源文件        super.onDetachedFromWindow();        stopAndRecyclerAnim(mUpdownAnim);        stopAndRecyclerAnim(mSpreadAnim);        recyclerBitmap(mUpdownMaskBitmap);        recyclerBitmap(mUnmaskBitmap);        recyclerBitmap(mSpreadMaskBitmap);        mUpdownPaint = null;    }    private void recyclerBitmap(Bitmap bitmap) {        if (bitmap != null && !bitmap.isRecycled()) {            bitmap.recycle();        }        bitmap = null;    }    private void stopAndRecyclerAnim(ValueAnimator animator) {        if (animator != null && animator.isRunning()) {            animator.cancel();        }        animator = null;        if(mSpreadAnim == null && mUpdownAnim == null){//两个动画都停止后,恢复成正常状态            mCurrAnim = ANIM_NO;            invalidate();        }    }    @Override    protected void onDraw(Canvas canvas) {        switch (mCurrAnim) {            case ANIM_NO:                drawUnmask(canvas);                break;            case ANIM_UP_DOWN:                drawUpDown(canvas);                break;            case ANIM_SPREAD:                drawSpread(canvas);                break;        }    }    private void drawUnmask(Canvas canvas) {        Bitmap bitmap = getUnmaskBitmap();        canvas.drawBitmap(bitmap, 0, 0, null);        recyclerBitmap(mUpdownMaskBitmap);        recyclerBitmap(mSpreadMaskBitmap);    }    private void drawUpDown(Canvas canvas) {        //绘制底图        Bitmap unmaskBitmap = getUnmaskBitmap();        canvas.drawBitmap(unmaskBitmap, 0, 0, null);        //绘制阴影部分        Bitmap maskBitmap = getUpdownMaskBitmap();        mUpdownPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        int top = mMaskOffsetY - getHeight() < 0 ? 0 : (int) mMaskOffsetY - getHeight();        canvas.drawBitmap(maskBitmap, new Rect(0, top, unmaskBitmap.getWidth(), (int) mMaskOffsetY), new Rect(0, top, getWidth(), (int) mMaskOffsetY), mUpdownPaint);        mUpdownPaint.setXfermode(null);    }    /**     * 绘制水波纹     */    private void drawSpread(Canvas canvas) {        //绘制水波纹        Bitmap maskBitmap = getSpreadMaskBitmap();        canvas.drawBitmap(maskBitmap, 0, 0, null);    }    private Bitmap getUnmaskBitmap() { //获取正常情况下的bitmap        if (mUnmaskBitmap != null)            return mUnmaskBitmap;        int width = getWidth();        int height = getHeight();        mUnmaskBitmap = createBitmapAndGcIfNecessary(width, height);        Canvas canvas = new Canvas(mUnmaskBitmap);        Drawable drawable = getDrawable();        drawable.setAlpha(255); //正常情况下,不透明。用drawable绘制到自己指定的canvas上,就会将drawable转换成bitmap        drawable.draw(canvas);        return mUnmaskBitmap;    }    private Bitmap getUpdownMaskBitmap() {        int width = getWidth();        int height = getHeight();        if (mUpdownMaskBitmap == null)            mUpdownMaskBitmap = createBitmapAndGcIfNecessary(width, height);        Canvas canvas = new Canvas(mUpdownMaskBitmap);        canvas.drawColor(0, PorterDuff.Mode.CLEAR);        canvas.clipRect(0, 0, width, mMaskOffsetY); //截取一部分区域,这样在绘制半透明的区域时就会只绘制截取到的部分        Drawable drawable = getDrawable();        drawable.setAlpha((int) (255 * ALPHA));        drawable.draw(canvas);        return mUpdownMaskBitmap;    }    private Bitmap getSpreadMaskBitmap() {        int width = getWidth();        int height = getHeight();        if (mSpreadMaskBitmap == null) {            mSpreadMaskBitmap = createBitmapAndGcIfNecessary(width, height);        }        Canvas canvas = new Canvas(mSpreadMaskBitmap);        canvas.drawColor(0, PorterDuff.Mode.CLEAR);        //画原来未变暗的图        Drawable drawable = getDrawable();        drawable.setAlpha(255);        drawable.draw(canvas);        int max = Math.max(getWidth(), getHeight()) / 2;        if(path == null) {            path = new Path();        }else{            path.reset();        }        if (mMaskoffsetRadius < max) { //从内往外扩散的是半透明的            path.addCircle(getWidth() / 2, getHeight() / 2, mMaskoffsetRadius, Path.Direction.CCW);            canvas.clipPath(path); //截取一个圆环,然后用drawable绘制,这样绘制的drawable就是一个半透明的的圆环了。            canvas.drawColor(0, PorterDuff.Mode.CLEAR);            drawable.setAlpha((int) (255 * ALPHA));            drawable.draw(canvas);        } else {//从内往外扩散的是不透明的            //外圈阴影  。首先绘制外圈半透明的            path.reset();            path.addCircle(getWidth() / 2, getHeight() / 2, max, Path.Direction.CCW);            canvas.clipPath(path);            canvas.drawColor(0, PorterDuff.Mode.CLEAR);            drawable.setAlpha((int) (255 * ALPHA));            drawable.draw(canvas);            //内圈正常            path.reset();            path.addCircle(getWidth() / 2, getHeight() / 2, mMaskoffsetRadius - max, Path.Direction.CCW);            canvas.clipPath(path);            canvas.drawColor(0, PorterDuff.Mode.CLEAR);            drawable.setAlpha(255);            drawable.draw(canvas);        }        return mSpreadMaskBitmap;    }    private Bitmap createBitmapAndGcIfNecessary(int width, int height) {        try {            return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        } catch (OutOfMemoryError e) {            System.gc();            return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        }    }    //----------------------------------------提供出去的方法---------------------------------    public void startUpDown() {        mCurrAnim = ANIM_UP_DOWN;        stopAndRecyclerAnim(mSpreadAnim);        mUpdownAnim = ValueAnimator.ofInt(0, getHeight() * 2);        mUpdownAnim.setDuration(2000);        mUpdownAnim.setRepeatCount(ValueAnimator.INFINITE);        mUpdownAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                mMaskOffsetY = (int) valueAnimator.getAnimatedValue();                invalidate();            }        });        mUpdownAnim.start();    }    public void stopUpDown() {        if (null != mUpdownAnim)            stopAndRecyclerAnim(mUpdownAnim);    }    public void startSpread() {        stopAndRecyclerAnim(mUpdownAnim);        mCurrAnim = ANIM_SPREAD;        int radius = Math.max(getWidth(), getHeight()) / 2;        mSpreadAnim = ValueAnimator.ofInt(0, radius * 2);        mSpreadAnim.setDuration(1000);        mSpreadAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                mMaskoffsetRadius = (int) valueAnimator.getAnimatedValue();                invalidate();            }        });        mSpreadAnim.setRepeatCount(2);        mSpreadAnim.start();    }    public boolean isAnimming() {        return mCurrAnim == ANIM_SPREAD || mCurrAnim == ANIM_UP_DOWN;    }}



0 0
原创粉丝点击