Make ripple fill whole View
Asked Answered
Z

3

10

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.

Zosi answered 30/12, 2017 at 12:57 Comment(5)
Which API do you have on the actual REAL test device? Unfortunately I think it (RippleDrawable) only works on API 21+ (Android 5.0, LOLLIPOP). support library 21 still won't make it work on older devices.Fewell
Yeah you are right. I tested it on API 26 Oreo. Would be great if the real solution works on API 14+Zosi
I think I've seen a library that can do that, get back to you if I find it.Fewell
@Zosi Try using this android:background="?android:attr/selectableItemBackground".if u are ok with libraries check this out android-arsenal.com/tag/167Treadmill
github.com/traex/RippleEffect library is the best I have tested. Easy to Implement and API 14 +.Fewell
L
7

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 enter image description here

Littleton answered 3/1, 2018 at 5:44 Comment(1)
Thank you for this great answer. I managed to implement this by myself and created a repo for it. I used the Animation class from API 11 and do not calculate all by myself like in the library so decide by yourself which version is best suited for you.Zosi
P
2

Ripple effect For Clickable Views


ripple effect for regular buttons will work by default in API 21, and for other
touchable views it can be achieved by specifying
android:background="?android:attr/selectableItemBackground"> In Java CODE int[] attrs = new int[]{R.attr.selectableItemBackground}; TypedArray typedArray = getActivity().obtainStyledAttributes(attrs); int backgroundResource = typedArray.getResourceId(0, 0); myView.setBackgroundResource(backgroundResource);

Buttons
 Button Image


Most buttons are made with several drawables. Usually you’ll have a pressed and
normal version of assets like this: /drawable/button.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/>
    <item android:drawable="@drawable/button_normal"/>
</selector>
If you have a custom button with selected state, your text color changes 
depending on the state, etc. So the default button background is not going
to work for you here. You can add this feedback for your own drawables and
for custom buttons by simply wrapping them in a ripple element: /drawable-v21/button.xml:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight">
    <item android:drawable="@drawable/button_normal" />
</ripple>

Using ?android:colorControlHighlight will give the ripple the same color as the built-in ripples in your app.

If you don’t like the default grey, you can specify what color you want android:colorControlHighlight to be in your theme.

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
    <item name="android:colorControlHighlight">@color/your_custom_color</item>
  </style>

</resources>

If you want the ripple to extend past the boundary of the view, then you can
instead use ?attr/selectableItemBackgroundBorderless. This works well with
ImageButtons and smaller Buttons that are part of a larger View:

Pre answered 5/1, 2018 at 7:36 Comment(0)
T
0

Try this i hope its work for you

Use android:foreground="@drawable/ripple"

instead of android:background="@drawable/ripple"

and also change android:radius="0dp" to 50dp or 100dp and check

Toadeater answered 8/1, 2018 at 9:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.