본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] Circular Reveal 만들기

by 돼지왕 왕돼지 2017. 7. 14.
반응형

 [android] Circular Reveal 만들기


http://frogermcs.github.io/InstaMaterial-concept-part-6-user-profile/

Android, animation, changeState, circular reveal, createcircularreveal, drawCircle, invalidate, lollipop, objectanimator, ondraw, OnStateChangeListener, paint, render thread, RevealBackgroundView, Setcolor, setCurrentRadius, setOnStateChangeListener, setstyle, setToFinishedFrame, shader, startFromLocation, viewanimationutils, [android] Circular Reveal 만들기, 성능


-

Circular reveal 을 만드는 방법은 여러가지가 있다.



-

ViewAnimationUtils.createCircularReveal() 은 Render thread 통해 animation 되기 때문에 Lollipop 이전 단말에서는 사용할 수 없는 방법이다.

하지만 Lollipop 이라면 가장 간단한 방법이다.



-

https://github.com/ozodrukh/CircularReveal


위의 링크는 Ginger 이상에서 사용할 수 있는 open source



-

Circle 이 아닌 Square 방식이라면 pivotX/Y 를 지정하고 scaleX/Y 를 조정하는 것만으로 손쉽게 만들 수 있다.



-

사용하기는 어렵지만 성능측면에서 효율적인 shader 를 사용하는 방법도 있다.

아래 링크는 shader 사용에 대한 guide 를 제공한다.

http://www.curious-creature.com/2012/12/13/android-recipe-2-fun-with-shaders/



-

Custom View 를 사용해서 만들 수도 있다.


public class RevealBackgroundView extends View {

    public static final int STATE_NOT_STARTED = 0;

    public static final int STATE_FILL_STARTED = 1;

    public static final int STATE_FINISHED = 2;


    private static final Interpolator INTERPOLATOR = new AccelerateInterpolator();

    private static final int FILL_TIME = 400;


    private int state = STATE_NOT_STARTED;


    private Paint fillPaint;

    private int currentRadius;

    ObjectAnimator revealAnimator;


    private int startLocationX;

    private int startLocationY;



    private OnStateChangeListener onStateChangeListener;


    public RevealBackgroundView(Context context) {

        super(context);

        init();

    }


    public RevealBackgroundView(Context context, AttributeSet attrs) {

        super(context, attrs);

        init();

    }


    public RevealBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {

        super(context, attrs, defStyleAttr);

        init();

    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)

    public RevealBackgroundView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

        super(context, attrs, defStyleAttr, defStyleRes);

        init();

    }


    private void init() {

        fillPaint = new Paint();

        fillPaint.setStyle(Paint.Style.FILL);

        fillPaint.setColor(Color.WHITE);

    }


    public void startFromLocation(int[] tapLocationOnScreen) {

        changeState(STATE_FILL_STARTED);

        startLocationX = tapLocationOnScreen[0];

        startLocationY = tapLocationOnScreen[1];

        revealAnimator = ObjectAnimator.ofInt(this, "currentRadius", 0, getWidth() + getHeight()).setDuration(FILL_TIME);

        revealAnimator.setInterpolator(INTERPOLATOR);

        revealAnimator.addListener(new AnimatorListenerAdapter() {

            @Override

            public void onAnimationEnd(Animator animation) {

                changeState(STATE_FINISHED);

            }

        });

        revealAnimator.start();

    }


    public void setToFinishedFrame() {

        changeState(STATE_FINISHED);

        invalidate();

    }


    @Override

    protected void onDraw(Canvas canvas) {

        if (state == STATE_FINISHED) {

            canvas.drawRect(0, 0, getWidth(), getHeight(), fillPaint);

        } else {

            canvas.drawCircle(startLocationX, startLocationY, currentRadius, fillPaint);

        }

    }


    private void changeState(int state) {

        if (this.state == state) {

            return;

        }


        this.state = state;

        if (onStateChangeListener != null) {

            onStateChangeListener.onStateChange(state);

        }

    }


    public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener) {

        this.onStateChangeListener = onStateChangeListener;

    }


    public void setCurrentRadius(int radius) {

        this.currentRadius = radius;

        invalidate();

    }


    public static interface OnStateChangeListener {

        void onStateChange(int state);

    }

}




반응형

댓글