自定义ViewGroup---点击控件时水波纹效果

自定义ViewGroup -点击控件时水波纹效果

                            ONE Goal,ONE Passion!

上效果图:
这里写图片描述

1,实现方式:

1,自定义ViewGriup继承至LinearLayout.
2,在点击此控件的时候,以点击的位置为圆心,以子view的两端到点击位置的最大距离为半径绘制圆形.
3,将需要实现水波纹效果的控件,在布局文件中放入此viewgroup中.

2,自定义viewgroup的代码:

public class MyFlowLayout extends LinearLayout {

    private float X;   //点击的x位置
    private float Y;   //点击的y位置
    private Paint mPaint = new Paint();
    private int measuredWidth;   //测量的宽度
    private int measuredHeight;  //测量的高度

    private int radius = 0;
    private int child_l;  //子view的左边界x坐标
    private int child_r;   //子view的右边界x坐标


    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            if (msg.what == 0) {
// 注:没有考虑子控件 layout_width < layout_height的情况             
                int radius_complate = (int) Math.max((X - child_l), (child_r - X));// 得到应该绘制的圆的半径

                if (radius < radius_complate) {

                    radius += 10;  //每次绘制的圆半径加10
                    postInvalidateDelayed(40);
                    handler.sendEmptyMessageDelayed(0, 10);
                } else {

                    radius = 0;
                    postInvalidateDelayed(40);
                    //当绘制完成后移除hanlder
                    handler.removeCallbacksAndMessages(null);

                }
            }


        }
    };

    public MyFlowLayout(Context context) {
        this(context, null);
    }

    public MyFlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        //指定画笔的颜色
        mPaint.setColor(getResources().getColor(R.color.mPaint_color));
    }

    /**
     * 在这里去监听点击事件,是因为,我们包裹的子view可能把事件消费掉,
     * 那么onTouchEvent就不能拿到事件了.
     *
     * @param ev
     * @return 一定要返回 --- super.dispatchTouchEvent(ev) 否则顶层父view讲不能进行事件分发(自己以及子view都不能得到事件)
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        X = ev.getX();
        Y = ev.getY();

        handler.sendEmptyMessageDelayed(0, 10);

        return super.dispatchTouchEvent(ev);
    }

    /**
     * 由于 继承的是LinearLayout  自己的形状已经知道,系统就不会调用此方法去绘制了.
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int WidthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {

            View child = getChildAt(i);
            child.measure(widthMeasureSpec, heightMeasureSpec);

            measuredWidth = child.getMeasuredWidth();
            measuredHeight = child.getMeasuredHeight();

        }


    }
    /**
     * 当调用postInvalidateDelayed();时会自动回调此函数
     * <p/>
     * Called by draw to draw the child views. This may be overridden
     * by derived classes to gain control just before its children are drawn
     * (but after its own view has been drawn).
     *
     * @param canvas the canvas on which to draw the view
     *               <p/>
     *               绘制自己的子view, 自己可能去重写这个方法为了控制子view的绘制,该方法在自己绘制完成后
     *               自己的子view绘制之前调用(就是在这里去绘制子view,肯定是子view绘制钱调用);
     */


    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);    // 如果把这一行去掉的话,那么布局中子view就不会显示了,不过画出来的水波纹还是会有


        View child = getChildAt(0);  //得到子view,一般都是包裹一个子view.


        int[] loc = new int[2];
        child.getLocationInWindow(loc);
        child_l = loc[0];
        child_r = child_l + measuredWidth;


        canvas.save();

        /**
         * drawCircle(mCenterX, mCenterY, mRevealRadius, mPaint)
         *
         * @param cx     The x-coordinate of the center of the cirle to be drawn   圆心的x坐标
         * @param cy     The y-coordinate of the center of the cirle to be drawn  圆心的y坐标
         * @param radius The radius of the cirle to be drawn                     圆的半径
         * @param paint  The paint used to draw the circle                      画圆使用的画笔
         */

        canvas.drawCircle(X, Y, radius, mPaint);
        canvas.restore();


    }


}

3,开始给系统控件添加水波纹效果:

将需要添加水波纹效果的控件,包裹进这个MyFlowLayout viewgroup中即可.


    <com.example.customview.view.MyFlowLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/my_layout">

        <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:enabled="true"
            android:text="点击"
             />

    </com.example.customview.view.MyFlowLayout>
注:没有考虑子控件 layout_width < layout_height 的情况 ,此中情况圆的半径应该重新计算.
真正的半径计算应该是:  点击点到控件left,top,right,bottom的最大距离.

另:笔者水平有限,如您看到此篇文章有任何纰漏,请指正!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值