1. 程式人生 > >Android 揭露效果相容低版本

Android 揭露效果相容低版本

 自定了一個ImageView,和Android揭露效果想同。

 

效果:

 

程式碼如下:  

CircularRevealImageView.java

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;

/**
 * Created by wuguangliang on 2018/11/22
 * <p>
 * 揭露效果
 * 和<code>ViewAnimationUtils.createCircularReveal</code>一樣
 */
public class CircularRevealImageView extends android.support.v7.widget.AppCompatImageView {
    private Path path;
    private float centerX, centerY, startRadius, endRadius;
    private Thread thread;
    private float r = 0;
    private int temp = 1;
    private int nanos;

    public CircularRevealImageView(Context context) {
        super(context);
        init();
    }

    public CircularRevealImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CircularRevealImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        path = new Path();
        path.addCircle(0, 0, 0, Path.Direction.CW);
        initRenderThread();
    }

    private void initRenderThread() {
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (r <= endRadius - startRadius && r >= 0) {
                    try {
                        Thread.sleep(0, nanos);
                        r += temp;
                        if (r < 0) {
                            r = 0;
                            break;
                        } else if (r > endRadius - startRadius) {
                            r = endRadius - startRadius;
                            break;
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                thread = null;
                if (r == 0) {
                    post(new Runnable() {
                        @Override
                        public void run() {
                            setImageBitmap(null);
                        }
                    });
                }
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas) {
        path = new Path();
        path.addCircle(centerX, centerY, r, Path.Direction.CW);
        canvas.clipPath(path);
        super.onDraw(canvas);
        invalidate();
    }

    /**
     * 開始動畫
     *
     * @param centerX     The x coordinate of the center of the animating circle, relative to
     *                    <code>view</code>.
     * @param centerY     The y coordinate of the center of the animating circle, relative to
     *                    <code>view</code>.
     * @param startRadius The starting radius of the animating circle.
     * @param endRadius   The ending radius of the animating circle.
     * @param nanos       執行時間,納秒
     */
    public void start(final float centerX, final float centerY, final float startRadius, final float endRadius, final int nanos) {
        temp = 1;
        this.centerX = centerX;
        this.centerY = centerY;
        this.startRadius = startRadius;
        this.endRadius = endRadius;
        this.nanos = nanos;
        if (thread == null) {
            initRenderThread();
        }
        if (!thread.isAlive()) {
            thread.start();
        }
    }

    /**
     * 返回動畫,直接返回到start的點。
     *
     * @param nanos 執行時間,ns
     */
    public void back(final int nanos) {
        this.nanos = nanos;
        temp = -1;
        if (thread == null) {
            initRenderThread();
        }
        if (!thread.isAlive()) {
            thread.start();
        }
    }

    /**
     * 返回動畫,返回到新的點
     *
     * @param centerX     The x coordinate of the center of the animating circle, relative to
     *                    <code>view</code>.
     * @param centerY     The y coordinate of the center of the animating circle, relative to
     *                    <code>view</code>.
     * @param startRadius The starting radius of the animating circle.
     * @param endRadius   The ending radius of the animating circle.
     * @param nanos       執行時間,ns
     */
    public void back(final float centerX, final float centerY, final float startRadius, final float endRadius, final int nanos) {
        this.centerX = centerX;
        this.centerY = centerY;
        this.startRadius = startRadius;
        this.endRadius = endRadius;
        this.nanos = nanos;
        r = endRadius - startRadius;
        temp = -1;
        if (thread == null) {
            initRenderThread();
        }
        if (!thread.isAlive()) {
            thread.start();
        }
    }

    @Override
    public void setBackgroundResource(int resId) {
        new Throwable("不可用,用了沒效果");
    }

    @Override
    public void setBackgroundDrawable(Drawable background) {
        new Throwable("不可用,用了沒效果");
    }

    @Override
    public void setBackground(Drawable background) {
        new Throwable("不可用,用了沒效果");
    }
}

使用方式:

MainActivity.java

 final CircularRevealImageView imageView = findViewById(R.id.my_image);

        findViewById(R.id.apex_btn_add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imageView.setImageDrawable(getResources().getDrawable(R.drawable.mbg_2_1));
                imageView.start(500, 900, 0, 1080,200);
            }
        });
        findViewById(R.id.apex_btn_remove).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imageView.back(200);
            }
        });