自定义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的最大距离.
另:笔者水平有限,如您看到此篇文章有任何纰漏,请指正!