LidongWen / RippleLayouts

水波纹触摸效果
5 stars 2 forks source link

效果固然好,但是相应的问题不少 #1

Open xhcui2008 opened 7 years ago

xhcui2008 commented 7 years ago

比如说,我嵌套fragment,当我在fragment里面点击以后,fragment发生位移然后该动画,仍然停留在远处不动,拦截原View的Onclick事件

LidongWen commented 7 years ago

你好,谢谢你得反馈,下一版本会解决这个问题。 这个问题是因为移动view后,相对应窗体上的rippleLayout的位置没有改变所导致的,目前是打算采用监听view的位置变化改变的方式来解决这个问题。 不知到你有没有其他方法和思路

xhcui2008 commented 7 years ago

想法倒是有,但是也存在问题,但是我的方案和你的方案是互补的,但是仍然有问题 我的方法是继承我需要使用的制定的View控件,然后在这个控件里面做动画,然后规定他只能随着动画运行,但是存在比如说Activity切换的时候,我点击这个View跳转,并且这个动画执行了一半,动画就暂停了,让从跳转的Activity返回以后,这个动画会继续运行,或者在popupwindow里面也会出现这个问题,

`public class RippleLinearLayout extends LinearLayout {

private Paint mPaint;
private int clickedViewWidth;
private int clickedViewHeight;

private int mMaxRippleRadius;
private int mRippleRadiusGap;
private int mRippleRadius = 0;
private float mCenterX;
private float mCenterY;
private int[] mLocationInScreen = new int[2];
private boolean shouldDrawRipple = false;
private boolean isPressed = false;
private int INVALIDATE_DURATION = 50;
private View clickedView;

private boolean isClickedParent = false;

public RippleLinearLayout(Context context) {
    super(context);
    init();
}

public RippleLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RippleLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    setWillNotDraw(false);
    mPaint.setColor(Color.argb(50, 170, 170, 170));
}

public void setRippleColor(int color) {
    mPaint.setColor(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);
}

@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 clickedView = getTouchTarget(this, x, y); if (clickedView != null && clickedView.isClickable() && clickedView.isEnabled()) { this.clickedView = clickedView; isClickedParent = false; initParamForRipple(event, clickedView,false); postInvalidateDelayed(INVALIDATE_DURATION); } else { this.clickedView = this; isClickedParent = true; RippleLinearLayout.this.setClickable(true); initParamForRipple(event, clickedView,true); postInvalidateDelayed(INVALIDATE_DURATION); }

    } else if (action == MotionEvent.ACTION_UP) {
        isPressed = false;
        RippleLinearLayout.this.setClickable(false);
        postInvalidateDelayed(INVALIDATE_DURATION);
        clickedView.performClick();
        return true;
    } else if (action == MotionEvent.ACTION_CANCEL) {
        isPressed = false;
        postInvalidateDelayed(INVALIDATE_DURATION);
    }

    return super.dispatchTouchEvent(event);
}

@Override
protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    if (!shouldDrawRipple) {
        return;
    }

    if (mRippleRadius > mMaxRippleRadius / 2) {
        mRippleRadius += mRippleRadiusGap * 4;
    } else {
        mRippleRadius += mRippleRadiusGap;
    }

    this.getLocationOnScreen(mLocationInScreen);
    int[] location = new int[2];
    clickedView.getLocationOnScreen(location);
    int left = location[0] - mLocationInScreen[0];
    int top = location[1] - mLocationInScreen[1];
    int right = left + clickedView.getMeasuredWidth();
    int bottom = top + clickedView.getMeasuredHeight();

    canvas.save();
    if (!isClickedParent) {
        canvas.clipRect(left, top, right, bottom);
    }
    canvas.drawCircle(mCenterX, mCenterY, mRippleRadius, mPaint);
    canvas.restore();

    if (mRippleRadius <= mMaxRippleRadius) {
        if (isClickedParent) {
            postInvalidateDelayed(INVALIDATE_DURATION);
        } else {
            postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);
        }

    } else if (!isPressed) {
        shouldDrawRipple = false;
        if (isClickedParent) {
            postInvalidateDelayed(INVALIDATE_DURATION);
        } else {
            postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);
        }
    }
}

private void initParamForRipple(MotionEvent event, View view, boolean isClickedParent) {
    mCenterX = event.getX();
    mCenterY = event.getY();
    if (isClickedParent) {
        clickedViewWidth = this.getMeasuredWidth();
        clickedViewHeight = this.getMeasuredHeight();
    } else {
        clickedViewWidth = view.getMeasuredWidth();
        clickedViewHeight = view.getMeasuredHeight();
    }
    mMaxRippleRadius = (int) Math.sqrt(clickedViewWidth * clickedViewWidth + clickedViewHeight * clickedViewHeight);
    mRippleRadius = 0;
    shouldDrawRipple = true;
    isPressed = true;
    mRippleRadiusGap = mMaxRippleRadius / 20;
}

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) && child != RippleLinearLayout.this) {
            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;
}

} public class RippleImageView extends ImageButton { public void animationCancel() { mRadiusAnimator.cancel(); } /* The m down x. / private float mDownX;

/* The m down y. / private float mDownY;

/* The m alpha factor. / private float mAlphaFactor;

/* The m density. / private float mDensity;

/* The m radius. / private float mRadius;

/* The m max radius. / private float mMaxRadius;

/* The m ripple color. / private int mRippleColor;

/* The m is animating. / private boolean mIsAnimating = false;

/* The m hover. / private boolean mHover = true;

/* The m radial gradient. / private RadialGradient mRadialGradient;

/* The m paint. / private Paint mPaint;

/* The m radius animator. / private ObjectAnimator mRadiusAnimator;

/**

}`

LidongWen commented 7 years ago

你得这个方案比较好解决,在view 退出视图 onDetachedFromWindow 方法内 停止动画就好了

xhcui2008 commented 7 years ago

哦,好的,谢谢你,不过希望我的思路,可以给你帮助

LidongWen commented 7 years ago

不客气。 相互学习

LidongWen commented 7 years ago

已经修复你提的bug