In my application I want to create a ripple which fills the whole view. Because it doesn't worked properly I created a minimal example app and tried it there but with no success.
My Layout looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:padding="16dp">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ripple"
android:onClick="onViewClicked" />
</LinearLayout>
And my drawable is defined like this:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#1E88E5"
android:radius="0dp">
<item
android:id="@android:id/mask"
android:drawable="@android:color/white" />
</ripple>
Here is a video how it looks currently. I want that the circle (I think its called hotspot officially) grows from the middel until it fills the whole View
. I'm not talking about the radius of the ripple which is consciously set to 0dp here. Do you have any ideas how I can achieve this?
EDIT: In the end I want to achieve something like this.
For everyone who do not want to read all the answers: I managed to implement it and create a repo for this. Fell free to use this in your project and send me pull requests.
You can achieve this effect by creating your custom RippleView. Draw circle on full view using onDraw
method and set Animation to that circle.
if (animationRunning) {
canvas.save();
if (rippleDuration <= timer * frameRate) {
animationRunning = false;
timer = 0;
durationEmpty = -1;
timerEmpty = 0;
// There is problem on Android M where canvas.restore() seems to be called automatically
// For now, don't call canvas.restore() manually on Android M (API 23)
if(Build.VERSION.SDK_INT != 23) {
canvas.restore();
}
invalidate();
if (onCompletionListener != null) onCompletionListener.onComplete(this);
return;
} else
canvasHandler.postDelayed(runnable, frameRate);
if (timer == 0)
canvas.save();
canvas.drawCircle(x, y, (radiusMax * (((float) timer * frameRate) / rippleDuration)), paint);
paint.setColor(Color.parseColor("#ffff4444"));
if (rippleType == 1 && originBitmap != null && (((float) timer * frameRate) / rippleDuration) > 0.4f) {
if (durationEmpty == -1)
durationEmpty = rippleDuration - timer * frameRate;
timerEmpty++;
final Bitmap tmpBitmap = getCircleBitmap((int) ((radiusMax) * (((float) timerEmpty * frameRate) / (durationEmpty))));
canvas.drawBitmap(tmpBitmap, 0, 0, paint);
tmpBitmap.recycle();
}
paint.setColor(rippleColor);
if (rippleType == 1) {
if ((((float) timer * frameRate) / rippleDuration) > 0.6f)
paint.setAlpha((int) (rippleAlpha - ((rippleAlpha) * (((float) timerEmpty * frameRate) / (durationEmpty)))));
else
paint.setAlpha(rippleAlpha);
}
else
paint.setAlpha((int) (rippleAlpha - ((rippleAlpha) * (((float) timer * frameRate) / rippleDuration))));
timer++;
}
The implementation is stolen from RippleEffect Library project. Find full implementation in library project.
To create circle from only center poistion use below method
/**
* Launch Ripple animation for the current view centered at x and y position
*
* @param x Horizontal position of the ripple center
* @param y Vertical position of the ripple center
*/
public void animateRipple(final float x, final float y) {
createAnimation(x, y);
}
/**
* Create Ripple animation centered at x, y
*
* @param x Horizontal position of the ripple center
* @param y Vertical position of the ripple center
*/
private void createAnimation(final float x, final float y) {
if (this.isEnabled() && !animationRunning) {
if (hasToZoom)
this.startAnimation(scaleAnimation);
radiusMax = Math.max(WIDTH, HEIGHT);
if (rippleType != 2)
radiusMax /= 2;
radiusMax -= ripplePadding;
if (isCentered || rippleType == 1) {
this.x = getMeasuredWidth() / 2;
this.y = getMeasuredHeight() / 2;
} else {
this.x = x;
this.y = y;
}
animationRunning = true;
if (rippleType == 1 && originBitmap == null)
originBitmap = getDrawingCache(true);
invalidate();
}
}
Output :
You can get circle that grows from the middle until it fills the whole View