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