文档章节

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

雪狼的开发故事
 雪狼的开发故事
发布于 2015/09/10 14:14
字数 559
阅读 481
收藏 1

在项目中想着在点击控件的同时实现一种最近流行的水波纹效果(其实用安卓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中

© 著作权归作者所有

雪狼的开发故事
粉丝 2
博文 12
码字总数 5829
作品 0
海淀
程序员
私信 提问
Canvas常用方法解析第一篇

1. 图像扭曲 Canvas中提供了一个drawBitmapMesh方法,通过该方法可以实现位图的扭曲效果,下面来分析一下这个方法: 注意:该方法在API的级别大于等于18时才支持硬件加速。 图1 图2 实现水波...

ForeverCy
2017/08/08
0
0
Android TabLayout选项卡点击选中Ripple水波纹

版权声明:本文为Zhang Phil原创文章,请不要转载! https://blog.csdn.net/zhangphil/article/details/82528036 Android TabLayout选项卡点击时候选中的Ripple水波纹 如果要实现自定义的Tab...

zhangphil
2018/09/08
0
0
仿Google原生桌面水波纹展开收起动画实现

前言 在之前的博客android如何给整个视图view圆角显示中有提到过如何实现对View显示进行圆角裁剪,其原理其实也比较简单。这里先看看动画效果。 View负责绘制显示的draw方法 因为View的draw方...

Ihesong
2018/04/16
0
0
超酷的计步器APP(一)——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m366917/article/details/52976877 超酷的计步器APP(一)——炫酷功能实现,自定义水波纹特效、自定义炫酷开...

Aduroidpc
2016/10/31
0
0
使用CSS实现逼真的水波纹点击效果

这篇文章特别介绍如何使用CSS来完成水波纹的效果。 div的层层叠叠 虽然webkit具有遮罩的能力(webkit mask),不过webkit虽然强大,但在跨浏览器上总是它的罩门,况且在性能上也是往往会造成...

果冻tfzwgd
05/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

让《强化学习(第2版)》架起一座通往强化学习经典知识宝库的桥梁

上交大计算科学与工程系俞凯教授,5分钟口述讲解,带你快速认识了解年度重磅图书《强化学习(第二版)》! 在 AlphaGo战胜李世石之后,AlphaZero以其完全凭借自我学习超越人类在各种棋类游戏...

博文视点Bv
31分钟前
6
0
TLA7-EVM开发板的处理器、NOR FLASH、DDR3

TLA7-EVM开发板是一款由广州创龙基于Xilinx Artix-7系列FPGA自主研发的核心板+底板方式的开发板,可快速评估FPGA性能。核心板尺寸仅70mm*50mm,底板采用沉金无铅工艺的6层板设计,专业的PCB...

Tronlong创龙
40分钟前
4
0
UUID的变种-有序

为了解决UUID无序的问题,NHibernate在其主键生成方式中提供了Comb算法(combined guid/timestamp)。保留GUID的10个字节,用另6个字节表示GUID生成的时间(DateTime)。 /// <summary> //...

Canaan_
40分钟前
5
0
Netty学习(6)——通道间数据传输

1. FileChannel实现通道间的数据传输 在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel传输到另外一个channel。 transferFrom() FileChannel的transferF...

江左煤郎
44分钟前
4
0
AngularDOM操作

gtandsn
45分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部