码迷,mamicode.com
首页 > 其他好文 > 详细

浅谈实现点击出现水波纹效果

时间:2015-09-10 16:14:23      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:

在项目中想着在点击控件的同时实现一种最近流行的水波纹效果(其实用安卓5.0的直接就有了)。

其实步骤很简单:

1、自定义view,继承LinearLayout,

public class RevealLayout extends LinearLayout implements Runnable {


    private static final String TAG = "DxRevealLayout";

    private static final boolean DEBUG = true;


    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


    private int mTargetWidth;

    private int mTargetHeight;

    private int mMinBetweenWidthAndHeight;

    private int mMaxBetweenWidthAndHeight;

    private int mMaxRevealRadius;

    private int mRevealRadiusGap;

    private int mRevealRadius = 0;

    private float mCenterX;

    private float mCenterY;

    private int[] mLocationInScreen = new int[2];


    private boolean mShouldDoAnimation = false;

    private boolean mIsPressed = false;

    private int INVALIDATE_DURATION = 40;


    private View mTouchTarget;

    private DispatchUpTouchEventRunnable mDispatchUpTouchEventRunnable = new DispatchUpTouchEventRunnable();


    public RevealLayout(Context context) {

        super(context);

        init();

    }


    public RevealLayout(Context context, AttributeSet attrs) {

        super(context, attrs);

        init();

    }


    @TargetApi(Build.VERSION_CODES.HONEYCOMB)

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

        super(context, attrs, defStyleAttr);

        init();

    }


    private void init() {

        setWillNotDraw(false);

        mPaint.setColor(getResources().getColor(R.color.reveal_color));

    }


    @Override

    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        super.onLayout(changed, l, t, r, b);

        this.getLocationOnScreen(mLocationInScreen);

    }


    private void initParametersForChild(MotionEvent event, View view) {

        mCenterX = event.getX() ;

        mCenterY = event.getY() ;

        mTargetWidth = view.getMeasuredWidth();

        mTargetHeight = view.getMeasuredHeight();

        mMinBetweenWidthAndHeight = Math.min(mTargetWidth, mTargetHeight);

        mMaxBetweenWidthAndHeight = Math.max(mTargetWidth, mTargetHeight);

        mRevealRadius = 0;

        mShouldDoAnimation = true;

        mIsPressed = true;

        mRevealRadiusGap = mMinBetweenWidthAndHeight / 8;


        int[] location = new int[2];

        view.getLocationOnScreen(location);

        int left = location[0] - mLocationInScreen[0];

        int transformedCenterX = (int)mCenterX - left;

        mMaxRevealRadius = Math.max(transformedCenterX, mTargetWidth - transformedCenterX);

    }


    protected void dispatchDraw(Canvas canvas) {

        super.dispatchDraw(canvas);

        if (!mShouldDoAnimation || mTargetWidth <= 0 || mTouchTarget == null) {

            return;

        }


        if (mRevealRadius > mMinBetweenWidthAndHeight / 2) {

            mRevealRadius += mRevealRadiusGap * 4;

        } else {

            mRevealRadius += mRevealRadiusGap;

        }

        this.getLocationOnScreen(mLocationInScreen);

        int[] location = new int[2];

        mTouchTarget.getLocationOnScreen(location);

        int left = location[0] - mLocationInScreen[0];

        int top = location[1] - mLocationInScreen[1];

        int right = left + mTouchTarget.getMeasuredWidth();

        int bottom = top + mTouchTarget.getMeasuredHeight();


        canvas.save();

        canvas.clipRect(left, top, right, bottom);

        canvas.drawCircle(mCenterX, mCenterY, mRevealRadius, mPaint);

        canvas.restore();


        if (mRevealRadius <= mMaxRevealRadius) {

            postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);

        } else if (!mIsPressed) {

            mShouldDoAnimation = false;

            postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);

        }

    }


    @Override

    public boolean dispatchTouchEvent(MotionEvent event) {

        int x = (int) event.getRawX();

        int y = (int) event.getRawY();

        int action = event.getAction();

        if (action == MotionEvent.ACTION_DOWN) {

            View touchTarget = getTouchTarget(this, x, y);

            if (touchTarget != null && touchTarget.isClickable() && touchTarget.isEnabled()) {

                mTouchTarget = touchTarget;

                initParametersForChild(event, touchTarget);

                postInvalidateDelayed(INVALIDATE_DURATION);

            }

        } else if (action == MotionEvent.ACTION_UP) {

            mIsPressed = false;

            postInvalidateDelayed(INVALIDATE_DURATION);

            mDispatchUpTouchEventRunnable.event = event;

            postDelayed(mDispatchUpTouchEventRunnable, 40);

            return true;

        } else if (action == MotionEvent.ACTION_CANCEL) {

            mIsPressed = false;

            postInvalidateDelayed(INVALIDATE_DURATION);

        }


        return super.dispatchTouchEvent(event);

    }


    private View getTouchTarget(View view, int x, int y) {

        View target = null;

        ArrayList<View> TouchableViews = view.getTouchables();

        for (View child : TouchableViews) {

            if (isTouchPointInView(child, x, y)) {

                target = child;

                break;

            }

        }


        return target;

    }


    private boolean isTouchPointInView(View view, int x, int y) {

        int[] location = new int[2];

        view.getLocationOnScreen(location);

        int left = location[0];

        int top = location[1];

        int right = left + view.getMeasuredWidth();

        int bottom = top + view.getMeasuredHeight();

        if (view.isClickable() && y >= top && y <= bottom

                && x >= left && x <= right) {

            return true;

        }

        return false;

    }


    @Override

    public boolean performClick() {

        postDelayed(this, 400);

        return true;

    }


    @Override

    public void run() {

        super.performClick();

    }


    private class DispatchUpTouchEventRunnable implements Runnable {

        public MotionEvent event;


        @Override

        public void run() {

            if (mTouchTarget == null || !mTouchTarget.isEnabled()) {

                return;

            }


            if (isTouchPointInView(mTouchTarget, (int)event.getRawX(), (int)event.getRawY())) {

                mTouchTarget.performClick();

            }

        }

    };


}

2、把你想要一点击就出现水波纹效果的控件放入继承LinearLayout的自定义view中

浅谈实现点击出现水波纹效果

标签:

原文地址:http://my.oschina.net/u/2439266/blog/504434

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!