我最近发现了以下代码:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class RippleViewCreator extends FrameLayout {
private float duration = 150;
private int frameRate = 15;
private float speed = 1;
private float radius = 0;
private Paint paint = new Paint();
private float endRadius = 0;
private float rippleX = 0;
private float rippleY = 0;
private int width = 0;
private int height = 0;
private Handler handler = new Handler();
private int touchAction;
public RippleViewCreator(Context context) {
this(context, null, 0);
}
public RippleViewCreator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RippleViewCreator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
if (isInEditMode())
return;
paint.setStyle(Paint.Style.FILL);
paint.setColor(getResources().getColor(R.color.control_highlight_color));
paint.setAntiAlias(true);
setWillNotDraw(true);
setDrawingCacheEnabled(true);
setClickable(true);
}
public static void addRippleToView(View v) {
ViewGroup parent = (ViewGroup) v.getParent();
int index = -1;
if (parent != null) {
index = parent.indexOfChild(v);
parent.removeView(v);
}
RippleViewCreator rippleViewCreator = new RippleViewCreator(v.getContext());
rippleViewCreator.setLayoutParams(v.getLayoutParams());
if (index == -1)
parent.addView(rippleViewCreator, index);
else
parent.addView(rippleViewCreator);
rippleViewCreator.addView(v);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
@Override
protected void dispatchDraw(@NonNull Canvas canvas) {
super.dispatchDraw(canvas);
if (radius > 0 && radius < endRadius) {
canvas.drawCircle(rippleX, rippleY, radius, paint);
if (touchAction == MotionEvent.ACTION_UP)
invalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return true;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
rippleX = event.getX();
rippleY = event.getY();
touchAction = event.getAction();
switch (event.getAction()) {
case MotionEvent.ACTION_UP: {
getParent().requestDisallowInterceptTouchEvent(false);
radius = 1;
endRadius = Math.max(Math.max(Math.max(width - rippleX, rippleX), rippleY), height - rippleY);
speed = endRadius / duration * frameRate;
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (radius < endRadius) {
radius += speed;
paint.setAlpha(90 - (int) (radius / endRadius * 90));
handler.postDelayed(this, frameRate);
} else if (getChildAt(0) != null) {
getChildAt(0).performClick();
}
}
}, frameRate);
break;
}
case MotionEvent.ACTION_CANCEL: {
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
case MotionEvent.ACTION_DOWN: {
getParent().requestDisallowInterceptTouchEvent(true);
endRadius = Math.max(Math.max(Math.max(width - rippleX, rippleX), rippleY), height - rippleY);
paint.setAlpha(90);
radius = endRadius / 3;
invalidate();
return true;
}
case MotionEvent.ACTION_MOVE: {
if (rippleX < 0 || rippleX > width || rippleY < 0 || rippleY > height) {
getParent().requestDisallowInterceptTouchEvent(false);
touchAction = MotionEvent.ACTION_CANCEL;
break;
} else {
invalidate();
return true;
}
}
}
invalidate();
return false;
}
@Override
public final void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) {
//limit one view
if (getChildCount() > 0) {
throw new IllegalStateException(this.getClass().toString() + " can only have one child.");
}
super.addView(child, index, params);
}
}
任何人都可以向我解释这个涟漪效应代码究竟是如何工作的,因为我一直试图理解它至少一天,我仍然无法理解它是如何工作的。
准确我不明白:
public static void addRippleToView(View v) {
ViewGroup parent = (ViewGroup) v.getParent();
int index = -1;
if (parent != null) {
index = parent.indexOfChild(v);
parent.removeView(v);
}
RippleViewCreator rippleViewCreator = new RippleViewCreator(v.getContext());
rippleViewCreator.setLayoutParams(v.getLayoutParams());
if (index == -1)
parent.addView(rippleViewCreator, index);
else
parent.addView(rippleViewCreator);
rippleViewCreator.addView(v);
}
答案 0 :(得分:1)
我不知道如果这个类实际上有效,但如果确实,那就是这样的猜测:
这个自定义视图是FrameLayout的子类,这意味着它希望有一个子视图。所以你要在你的视图XML中声明它并给它一个子项放在它的边界内。
当它在onTouchEVent中收到触摸事件时,会绘制一个动画涟漪效果,该效果会出现在它包含的视图后面。
开发人员也可以告诉这个RippleViewCreator通过调用addRippleToView在它包含的特定视图后面呈现涟漪效果。看起来这个方法从视图层次结构中删除了目标子视图,将其包装在另一个RippleViewCreator中,并将 添加回自己的视图层次结构中以获得波纹动画。
疯狂的东西,伙计。