package com.yydcdut.noteplugin.view;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Property;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import com.yydcdut.noteplugin.R;
import static android.view.GestureDetector.SimpleOnGestureListener;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class MaterialRippleLayout extends FrameLayout {
private static final int DEFAULT_DURATION = 350;
private static final int DEFAULT_FADE_DURATION = 75;
private static final float DEFAULT_DIAMETER_DP = 35;
private static final float DEFAULT_ALPHA = 0.2f;
private static final int DEFAULT_COLOR = Color.BLACK;
private static final int DEFAULT_BACKGROUND = Color.TRANSPARENT;
private static final boolean DEFAULT_HOVER = true;
private static final boolean DEFAULT_DELAY_CLICK = true;
private static final boolean DEFAULT_PERSISTENT = false;
private static final boolean DEFAULT_SEARCH_ADAPTER = false;
private static final boolean DEFAULT_RIPPLE_OVERLAY = false;
private static final int DEFAULT_ROUNDED_CORNERS = 0;
private static final int FADE_EXTRA_DELAY = 50;
private static final long HOVER_DURATION = 2500;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Rect bounds = new Rect();
private int rippleColor;
private boolean rippleOverlay;
private boolean rippleHover;
private int rippleDiameter;
private int rippleDuration;
private int rippleAlpha;
private boolean rippleDelayClick;
private int rippleFadeDuration;
private boolean ripplePersistent;
private Drawable rippleBackground;
private boolean rippleInAdapter;
private float rippleRoundedCorners;
private float radius;
private AdapterView parentAdapter;
/**
* 子view
*/
private View childView;
private AnimatorSet rippleAnimator;
private ObjectAnimator hoverAnimator;
private Point currentCoords = new Point();
private Point previousCoords = new Point();
private int layerType;
private boolean eventCancelled;
private boolean prepressed;
private int positionInAdapter;
private GestureDetector gestureDetector;
private PerformClickEvent pendingClickEvent;
private PressedEvent pendingPressEvent;
public static RippleBuilder on(View view) {
return new RippleBuilder(view);
}
public MaterialRippleLayout(Context context) {
this(context, null, 0);
}
public MaterialRippleLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MaterialRippleLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(false);
gestureDetector = new GestureDetector(context, longClickListener);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRippleLayout);
rippleColor = a.getColor(R.styleable.MaterialRippleLayout_mrl_rippleColor, DEFAULT_COLOR);
rippleDiameter = a.getDimensionPixelSize(
R.styleable.MaterialRippleLayout_mrl_rippleDimension,
(int) dpToPx(getResources(), DEFAULT_DIAMETER_DP)
);
rippleOverlay = a.getBoolean(R.styleable.MaterialRippleLayout_mrl_rippleOverlay, DEFAULT_RIPPLE_OVERLAY);
rippleHover = a.getBoolean(R.styleable.MaterialRippleLayout_mrl_rippleHover, DEFAULT_HOVER);
rippleDuration = a.getInt(R.styleable.MaterialRippleLayout_mrl_rippleDuration, DEFAULT_DURATION);
rippleAlpha = (int) (255 * a.getFloat(R.styleable.MaterialRippleLayout_mrl_rippleAlpha, DEFAULT_ALPHA));
rippleDelayClick = a.getBoolean(R.styleable.MaterialRippleLayout_mrl_rippleDelayClick, DEFAULT_DELAY_CLICK);
rippleFadeDuration = a.getInteger(R.styleable.MaterialRippleLayout_mrl_rippleFadeDuration, DEFAULT_FADE_DURATION);
rippleBackground = new ColorDrawable(a.getColor(R.styleable.MaterialRippleLayout_mrl_rippleBackground, DEFAULT_BACKGROUND));
ripplePersistent = a.getBoolean(R.styleable.MaterialRippleLayout_mrl_ripplePersistent, DEFAULT_PERSISTENT);
rippleInAdapter = a.getBoolean(R.styleable.MaterialRippleLayout_mrl_rippleInAdapter, DEFAULT_SEARCH_ADAPTER);
rippleRoundedCorners = a.getDimensionPixelSize(R.styleable.MaterialRippleLayout_mrl_rippleRoundedCorners, DEFAULT_ROUNDED_CORNERS);
a.recycle();
paint.setColor(rippleColor);
paint.setAlpha(rippleAlpha);
enableClipPathSupportIfNecessary();
}
@SuppressWarnings("unchecked")
public <T extends View> T getChildView() {
return (T) childView;
}
@Override
public final void addView(View child, int index, ViewGroup.LayoutParams params) {
//只能有1个子view
if (getChildCount() > 0) {
throw new IllegalStateException("MaterialRippleLayout can host only one child");
}
//noinspection unchecked
childView = child;
super.addView(child, index, params);
}
@Override
public void setOnClickListener(OnClickListener onClickListener) {
if (childView == null) {
throw new IllegalStateException("MaterialRippleLayout must have a child view to handle clicks");
}
//把监听器传给子view
childView.setOnClickListener(onClickListener);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
//可点击,返回true,那么return过去的就是false,就么与拦截touch事件1
//不可点击,则返回false,那么return过去的就是true,那么就拦截了点击事件
return !findClickableViewInChild(childView, (int) event.getX(), (int) event.getY());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//父类的返回方法
boolean superOnTouchEvent = super.onTouchEvent(event);
//自己是enable并且子view不能enable的话,返回父类的事件
if (!isEnabled() || !childView.isEnabled()) {
return superOnTouchEvent;
}
//touch的地方是不是在边界内
boolean isEventInBounds = bounds.contains((int) event.getX(), (int) event.getY());
//如果在边界内
if (isEventInBounds) {
previousCoords.set(currentCoords.x, currentCoords.y);
currentCoords.set((int) event.getX(), (int) event.getY());
}
boolean gestureResult = gestureDetector.onTouchEvent(event);
if (gestureResult || mHasPerformedLongPress) {
return true;
} else {
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
pendingClickEvent = new PerformClickEvent();
if (prepressed) {
childView.setPressed(true);
postDelayed(
new Runnable() {
@Override
public void run() {
childView.setPressed(false);
}
}, ViewConfiguration.getPressedStateDuration());
}
if (isEventInBounds) {
startRipple(pendingClickEvent);
} else if (!rippleHover) {
setRadius(0);
}
if (!rippleDelayClick && isEventInBounds) {
pendingClickEvent.run();
}
cancelPressedEvent();
break;
case MotionEvent.ACTION_DOWN:
setPositionInAdapter();
eventCancelled = false;
pendingPressEvent = new PressedEvent(event);
if (isInScrollingContainer()) {
cancelPressedEvent();
prepressed = true;
postDelayed(pendingPressEvent, ViewConfiguration.getTapTimeout());
} else {
pendingPressEvent.run();
}
break;
case MotionEvent.ACTION_CANCEL:
if (rippleInAdapter) {
// dont use current coords in adapter since they tend to jump drastically on scroll
currentCoords.set(previousCoords.x, previousCoords.y);
previousCoords = new Point();
}
childView.onTouchEvent(event);
if (rippleHover) {
if (!prepressed) {
startRipple(null);
}
} else {
childView.setPressed(false);
}
cancelPressedEvent();
break;
case MotionEvent.ACTION_MOVE:
if (rippleHover) {
if (isEventInBounds && !eventCancelled) {
invalidate();
} else if (!isEventInBounds) {
startRipple(null);
}
}
if (!isEventInBounds) {
cancelPressedEvent();
if (hoverAnimator != null) {
hoverAnimator.cancel();
}
childView.onTouchEvent(event);
eventCancelled = true;
}
break;
}
return true;
}
}
private void cancelPressedEvent() {
if (pendingPressEvent != null) {
removeCallbacks(pendingPressEvent);
prepressed = false;
}
}
private boolean mHasPerformedLongPress;
private SimpleOnGestureListener longClickListener = new SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
//传递给子view
mHasPerformedLongPress = childView.performLongClick();
if (mHasPerformedLongPress) {
if (rippleHover) {
startRipple(null);
}
cancelPressedEvent();
}
}
@Override
public boolean onDown(MotionEvent e) {
mHasPerformedLongPress = false;
return super.onDown(e);
}
};
/**
* 开始覆盖
*/
private void startHover() {
//
if (eventCancelled) {
return;
}
//上一次动画还没完,cancel掉
if (hoverAnimator != null) {
hoverAnimator.cancel();
}
final float radius = (float) (Math.sqrt(Math.pow(getWidth(), 2) + Math.pow(getHeight(), 2)) * 1.2f);
hoverAnimator = ObjectAnimator.ofFloat(this, radiusProperty, rippleDiameter, radius)
.setDuration(HOVER_DURATION);
//设置interpolator
hoverAnimator.setInterpolator(new LinearInterpolator());
//动画开始
hoverAnimator.start();
}
private void startRipple(final Runnable animationEndRunnable) {
if (eventCancelled) {
return;
}
float endRadius = getEndRadius();
cancelAnimations();
rippleAnimator = new AnimatorSet();
rippleAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!ripplePersistent) {
setRadius(0);
setRippleAlpha(rippleAlpha);
}
if (animationEndRunnable != null && rippleDelayClick) {
animationEndRunnable.run();
}
childView.setPressed(false);
}
});
ObjectAnimator ripple = ObjectAnimator.ofFloat(this, radiusProperty, radius, endRadius);
ripple.setDuration(rippleDuration);
ripple.setInterpolator(new DecelerateInterpolator());
ObjectAnimator fade = ObjectAnimator.ofInt(this, circleAlphaProperty, rippleAlpha, 0);
fade.setDuration(rippleFadeDuration);
fade.setInterpolator(new AccelerateInterpolator());
fade.setStartDelay(rippleDuration - rippleFadeDuration - FADE_EXTRA_DELAY);
if (ripplePersistent) {
rippleAnimator.play(ripple);
} else if (getRadius() > endRadius) {
fade.setStartDelay(0);
rippleAnimator.play(fade);
} else {
rippleAnimator.playTogether(ripple, fade);
}
rippleAnimator.start();
}
private void cancelAnimations() {
if (rippleAnimator != null) {
rippleAnimator.cancel();
rippleAnimator.removeAllListeners();
}
if (hoverAnimator != null) {
hoverAnimator.cancel();
}
}
private float getEndRadius() {
final int width = getWidth();
final int height = getHeight();
final int halfWidth = width / 2;
final int halfHeight = height / 2;
final float radiusX = halfWidth > currentCoords.x ? width - currentCoords.x : currentCoords.x;
final float radiusY = halfHeight > currentCoords.y ? height - currentCoords.y : currentCoords.y;
return (float) Math.sqrt(Math.pow(radiusX, 2) + Math.pow(radiusY, 2)) * 1.2f;
}
private boolean isInScrollingContainer() {
ViewParent p = getParent();
while (p != null && p instanceof ViewGroup) {
if (((ViewGroup) p).shouldDelayChildPressedState()) {
return true;
}
p = p.getParent();
}
return false;
}
/**
* 找到父类,这个父类是一个adapterView
*
* @return
*/
private AdapterView findParentAdapterView() {
if (parentAdapter != null) {
return parentAdapter;
}
//如果再adapter里面的话,那么找到父类
ViewParent current = getParent();
while (true) {
if (current instanceof AdapterView) {
//直到找到AdapterView
parentAdapter = (AdapterView) current;
return parentAdapter;
} else {
//没有找到的话继续往前面找,知道找到
try {
current = current.getParent();
} catch (NullPointerException npe) {
throw new RuntimeException("Could not find a parent AdapterView");
}
}
}
}
/**
* 找到view再adapterview中的位置
*/
private void setPositionInAdapter() {
//view是不是再adpaterview中
if (rippleInAdapter) {
//找到当前位置,position
positionInAdapter = findParentAdapterView().getPositionForView(MaterialRippleLayout.this);
}
}
/**
* @return
*/
private boolean adapterPositionChanged() {
if (rippleInAdapter) {//判断这个view是不是再adapter里面
//找到在adapterview中的位置
int newPosition = findParentAdapterView().getPositionForView(MaterialRippleLayout.this);
//判断于之前比,位置是否发生改变
final boolean changed = newPosition != positionInAdapter;
//把新获取出来的位置赋值给全局变量
positionInAdapter = newPosition;
//如果位置是发生了变化的
if (changed) {
cancelPressedEvent();
cancelAnimations();
childView.setPressed(false);
setRadius(0);
}
return changed;
}
return false;
}
/**
* 判断要传递给的view是否可以点击,如果可以点击之类的,返回true,如果不能则false
*
* @param view 子view
* @param x
* @param y
* @return
*/
private boolean findClickableViewInChild(View view, int x, int y) {
if (view instanceof ViewGroup) {//判断子view是不是viewgroup
ViewGroup viewGroup = (ViewGroup) view;//强转viewgroup
for (int i = 0; i < viewGroup.getChildCount(); i++) {//便利子子view
View child = viewGroup.getChildAt(i);//拿到子子view
final Rect rect = new Rect();
child.getHitRect(rect);//获得子子view位置
final boolean contains = rect.contains(x, y);//判断x,y坐标是否在这个位置上
if (contains) {//如果找到了,那么再去便利,递归,直到找到这个view不是viewgroup
return findClickableViewInChild(child, x - rect.left, y - rect.top);
}
}
} else if (view != childView) {//如果不是ziview,那么判断是否可以点击之类的
return (view.isEnabled() && (view.isClickable() || view.isLongClickable() || view.isFocusableInTouchMode()));
}
//直接返回是不是可以isFocusableInTouchMode
return view.isFocusableInTouchMode();
}
/**
* 先调用onSizeChanged再调用的onDraw
* 这个时候将view的大小传进去,将rippleBackground的边界找到
*
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bounds.set(0, 0, w, h);
rippleBackground.setBounds(bounds);
}
@Override
public boolean isInEditMode() {
return true;
}
/*
* Drawing
*/
@Override
public void draw(Canvas canvas) {
final boolean positionChanged = adapterPositionChanged();
if (rippleOverlay) {
if (!positionChanged) {
rippleBackground.draw(canvas);
}
super.draw(canvas);
if (!positionChanged) {
if (rippleRoundedCorners != 0) {
Path clipPath = new Path();
RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
canvas.clipPath(clipPath);
}
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
} else {
if (!positionChanged) {
rippleBackground.draw(canvas);
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
super.draw(canvas);
}
}
/*
* Animations
*/
private Property<MaterialRippleLayout, Float> radiusProperty
= new Property<MaterialRippleLayout, Float>(Float.class, "radius") {
@Override
public Float get(MaterialRippleLayout object) {
return object.getRadius();
}
@Override
public void set(MaterialRippleLayout object, Float value) {
object.setRadius(value);
}
};
private float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
invalidate();
}
private Property<MaterialRippleLayout, Integer> circleAlphaProperty
= new Property<MaterialRippleLayout, Integer>(Integer.class, "rippleAlpha") {
@Override
public Integer get(MaterialRippleLayout object) {
return object.getRippleAlpha();
}
@Override
public void set(MaterialRippleLayout object, Integer value) {
object.setRippleAlpha(value);
}
};
public int getRippleAlpha() {
return paint.getAlpha();
}
public void setRippleAlpha(Integer rippleAlpha) {
paint.setAlpha(rippleAlpha);
invalidate();
}
/*
* Accessor
*/
public void setRippleColor(int rippleColor) {
this.rippleColor = rippleColor;
paint.setColor(rippleColor);
paint.setAlpha(rippleAlpha);
invalidate();
}
public void setRippleOverlay(boolean rippleOverlay) {
this.rippleOverlay = rippleOverlay;
}
public void setRippleDiameter(int rippleDiameter) {
this.rippleDiameter = rippleDiameter;
}
public void setRippleDuration(int rippleDuration) {
this.rippleDuration = rippleDuration;
}
public void setRippleBackground(int color) {
rippleBackground = new ColorDrawable(color);
rippleBackground.setBounds(bounds);
invalidate();
}
public void setRippleHover(boolean rippleHover) {
this.rippleHover = rippleHover;
}
public void setRippleDelayClick(boolean rippleDelayClick) {
this.rippleDelayClick = rippleDelayClick;
}
public void setRippleFadeDuration(int rippleFadeDuration) {
this.rippleFadeDuration = rippleFadeDuration;
}
public void setRipplePersistent(boolean ripplePersistent) {
this.ripplePersistent = ripplePersistent;
}
public void setRippleInAdapter(boolean rippleInAdapter) {
this.rippleInAdapter = rippleInAdapter;
}
public void setRippleRoundedCorners(int rippleRoundedCorner) {
this.rippleRoundedCorners = rippleRoundedCorner;
enableClipPathSupportIfNecessary();
}
public void setDefaultRippleAlpha(int alpha) {
this.rippleAlpha = alpha;
paint.setAlpha(alpha);
invalidate();
}
public void performRipple() {
currentCoords = new Point(getWidth() / 2, getHeight() / 2);
startRipple(null);
}
public void performRipple(Point anchor) {
currentCoords = new Point(anchor.x, anchor.y);
startRipple(null);
}
/**
* {@link Canvas#clipPath(Path)} is not supported in hardware accelerated layers
* before API 18. Use software layer instead
* <p>
* https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void enableClipPathSupportIfNecessary() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (rippleRoundedCorners != 0) {
layerType = getLayerType();
setLayerType(LAYER_TYPE_SOFTWARE, null);
} else {
setLayerType(layerType, null);
}
}
}
}
/*
* Helper
*/
private class PerformClickEvent implements Runnable {
@Override
public void run() {
if (mHasPerformedLongPress) {
return;
}
// if parent is an AdapterView, try to call its ItemClickListener
if (getParent() instanceof AdapterView) {
clickAdapterView((AdapterView) getParent());
} else if (rippleInAdapter) {
// find adapter view
clickAdapterView(findParentAdapterView());
} else {
// otherwise, just perform click on child
childView.performClick();
}
}
private void clickAdapterView(AdapterView parent) {
final int position = parent.getPositionForView(MaterialRippleLayout.this);
final long itemId = parent.getAdapter() != null
? parent.getAdapter().getItemId(position)
: 0;
if (position != AdapterView.INVALID_POSITION) {
parent.performItemClick(MaterialRippleLayout.this, position, itemId);
}
}
}
/**
*
*/
private final class PressedEvent implements Runnable {
private final MotionEvent event;
public PressedEvent(MotionEvent event) {
this.event = event;
}
@Override
public void run() {
prepressed = false;
childView.setLongClickable(false);//prevent the child's long click,let's the ripple layout call it's performLongClick
childView.onTouchEvent(event);
childView.setPressed(true);
if (rippleHover) {
startHover();
}
}
}
static float dpToPx(Resources resources, float dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
}
/**
* Builder
*/
public static class RippleBuilder {
private final Context context;
private final View child;
private int rippleColor = DEFAULT_COLOR;
private boolean rippleOverlay = DEFAULT_RIPPLE_OVERLAY;
private boolean rippleHover = DEFAULT_HOVER;
private float rippleDiameter = DEFAULT_DIAMETER_DP;
private int rippleDuration = DEFAULT_DURATION;
private float rippleAlpha = DEFAULT_ALPHA;
private boolean rippleDelayClick = DEFAULT_DELAY_CLICK;
private int rippleFadeDuration = DEFAULT_FADE_DURATION;
private boolean ripplePersistent = DEFAULT_PERSISTENT;
private int rippleBackground = DEFAULT_BACKGROUND;
private boolean rippleSearchAdapter = DEFAULT_SEARCH_ADAPTER;
private float rippleRoundedCorner = DEFAULT_ROUNDED_CORNERS;
public RippleBuilder(View child) {
this.child = child;
this.context = child.getContext();
}
public RippleBuilder rippleColor(int color) {
this.rippleColor = color;
return this;
}
public RippleBuilder rippleOverlay(boolean overlay) {
this.rippleOverlay = overlay;
return this;
}
public RippleBuilder rippleHover(boolean hover) {
this.rippleHover = hover;
return this;
}
public RippleBuilder rippleDiameterDp(int diameterDp) {
this.rippleDiameter = diameterDp;
return this;
}
public RippleBuilder rippleDuration(int duration) {
this.rippleDuration = duration;
return this;
}
public RippleBuilder rippleAlpha(float alpha) {
this.rippleAlpha = 255 * alpha;
return this;
}
public RippleBuilder rippleDelayClick(boolean delayClick) {
this.rippleDelayClick = delayClick;
return this;
}
public RippleBuilder rippleFadeDuration(int fadeDuration) {
this.rippleFadeDuration = fadeDuration;
return this;
}
public RippleBuilder ripplePersistent(boolean persistent) {
this.ripplePersistent = persistent;
return this;
}
public RippleBuilder rippleBackground(int color) {
this.rippleBackground = color;
return this;
}
public RippleBuilder rippleInAdapter(boolean inAdapter) {
this.rippleSearchAdapter = inAdapter;
return this;
}
public RippleBuilder rippleRoundedCorners(int radiusDp) {
this.rippleRoundedCorner = radiusDp;
return this;
}
public MaterialRippleLayout create() {
MaterialRippleLayout layout = new MaterialRippleLayout(context);
layout.setRippleColor(rippleColor);
layout.setDefaultRippleAlpha((int) rippleAlpha);
layout.setRippleDelayClick(rippleDelayClick);
layout.setRippleDiameter((int) dpToPx(context.getResources(), rippleDiameter));
layout.setRippleDuration(rippleDuration);
layout.setRippleFadeDuration(rippleFadeDuration);
layout.setRippleHover(rippleHover);
layout.setRipplePersistent(ripplePersistent);
layout.setRippleOverlay(rippleOverlay);
layout.setRippleBackground(rippleBackground);
layout.setRippleInAdapter(rippleSearchAdapter);
layout.setRippleRoundedCorners((int) dpToPx(context.getResources(), rippleRoundedCorner));
ViewGroup.LayoutParams params = child.getLayoutParams();
ViewGroup parent = (ViewGroup) child.getParent();
int index = 0;
if (parent != null && parent instanceof MaterialRippleLayout) {
throw new IllegalStateException("MaterialRippleLayout could not be created: parent of the view already is a MaterialRippleLayout");
}
if (parent != null) {
index = parent.indexOfChild(child);
parent.removeView(child);
}
layout.addView(child, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
if (parent != null) {
parent.addView(layout, index, params);
}
return layout;
}
}
}