Android 实现单击View,中间出现水波纹效果,在执行点击事件。

来源:互联网 发布:xp网络共享打印机设置 编辑:程序博客网 时间:2024/04/30 02:20

1.自定义布局

package com.example.waterview;


import java.util.ArrayList;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;


public class WaterLinearLayout extends LinearLayout implements Runnable{


private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    
    // 被点击的控件的宽高    
    private int mTargetWidth;    
    private int mTargetHeight;    
    
    // mMaxRadius为绘制的水波纹圆圈最大的半径    
    private int mMaxRevealRadius;    
    // mRevealRadiusGap为每次重新绘制半径增加的值    
    private int mRevealRadiusGap;    
    // mRevealRadius为初始的数值    
    private int mRevealRadius = 0;    
    // 获取自定义控件WaterLinearLayout 在屏幕上的位置    
    private int[] mLocationInScreen = new int[2];    
    // 是否执行动画    
    private boolean mShouldDoAnimation = false;    
    private MotionEvent mchildEvent;
    // 重新绘制的时间 单位毫秒    
    private int INVALIDATE_DURATION = 80;    
    // mTouchTarget指的是用户点击的那个view    
    private View mTouchTarget;    
    // 松手的事件分发线程    
    private DispatchUpTouchEventRunnable mDispatchUpTouchEventRunnable = new DispatchUpTouchEventRunnable();    
    
    public WaterLinearLayout(Context context)    
    {    
        super(context);    
        init();    
    }    
    
    public WaterLinearLayout(Context context, AttributeSet attrs)    
    {    
        super(context, attrs);    
        init();    
    }    
       
    public WaterLinearLayout(Context context, AttributeSet attrs, int defStyleAttr)    
    {    
        super(context, attrs, defStyleAttr);    
        init();    
    }    
    
    private void init()    
    {    
        setWillNotDraw(false);    
        mPaint.setColor(getResources().getColor(R.color.waterline_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)    
    {     
        mTargetWidth = view.getMeasuredWidth();    
        mTargetHeight = view.getMeasuredHeight();       
        mRevealRadius = 0;    
        mShouldDoAnimation = true;     
        mMaxRevealRadius = Math.min(mTargetHeight/2, mTargetWidth/2);   
        mRevealRadiusGap = mMaxRevealRadius / 32;  
    }   
    
    /**  
     * 绘制水波  
     */    
    protected void dispatchDraw(Canvas canvas)    
    {    
        super.dispatchDraw(canvas);    
        if (!mShouldDoAnimation || mTargetWidth <= 0 || mTouchTarget == null)    
        {    
            return;    
        }  
        
        
        mRevealRadius += mRevealRadiusGap;      
        this.getLocationOnScreen(mLocationInScreen);    
        int[] location = new int[2];    
        mTouchTarget.getLocationOnScreen(location);    
        // 获得要绘制View的left, top, right, bottom值    
        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(mTargetWidth/2+left, top+mTargetHeight/2, mRevealRadius, mPaint);    
        canvas.restore();    
    
        if (mRevealRadius <= mMaxRevealRadius)    
        {    
            postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);    
        } else{    
            mShouldDoAnimation = false;  
            postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);     
            mDispatchUpTouchEventRunnable.event = mchildEvent;  
postDelayed(mDispatchUpTouchEventRunnable, 50); 
        }    
    }    
    
    @Override    
    public boolean dispatchTouchEvent(MotionEvent event)    
    {    
    mchildEvent = 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)    
        {     
            postInvalidateDelayed(INVALIDATE_DURATION); 
            return true;    
        } else if (action == MotionEvent.ACTION_CANCEL)    
        {    
            postInvalidateDelayed(INVALIDATE_DURATION);    
        }    
    
        return super.dispatchTouchEvent(event);    
    }    
    
    /**  
     * 遍历view树找到用户所点击的那个view  
     *   
     * @param view  
     * @param x  
     * @param y  
     * @return  
     */    
    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;    
    }    
    
    /**  
     * 判断事件的xy是否落在view的上下左右四个角之内  
     *   
     * @param view  
     * @param x  
     * @param y  
     * @return  
     */    
    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.xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


    <com.example.waterview.WaterLinearLayout
        android:layout_width="400dp"
        android:layout_height="500dp"
        android:padding="50dp"
        android:orientation="vertical" >


        <Button
            android:onClick="close"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:text="关闭" 
            android:background="@drawable/close_selector"/>
    </com.example.waterview.WaterLinearLayout>
    


</RelativeLayout>

3.按钮效果close_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
      <item android:drawable="@drawable/image02" android:state_pressed="true"/>
  <item android:drawable="@drawable/gougou2" android:state_focused="false" android:state_pressed="false"/> 
</selector>

4.主函数程序

package com.example.waterview;


import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;


public class MainActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}


public void close(View view){
// Toast.makeText(this, "关闭", 0).show();
Log.d("MainActivity", "close");
}
}

0 0
原创粉丝点击