Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make ripple fill whole View

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.

like image 824
Cilenco Avatar asked Dec 30 '17 12:12

Cilenco


People also ask

How do I add a ripple effect to a View?

android:attr/selectableItemBackground”: this creates ripple effect with border. android:background=”? android:attr/selectableItemBackgroundBorderless”: this creates ripple effect without border.

What is ripple effect in Android?

Ripple touch effect was introduced with material design in Android 5.0 (API level 21). Touch feedback in material design provides an instantaneous visual confirmation at the point of contact when users interact fwith UI elements.

What is ripple color?

Ripple's logo comprises three colours: blue and teal gradient for the triskelion (symbol), and grey for the logotype. These colours have been extracted from the Ripple Style Guide.


2 Answers

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:

like image 81
Mallikarjuna Avatar answered Oct 17 '22 09:10

Mallikarjuna


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

like image 22
Dipali Shah Avatar answered Oct 17 '22 09:10

Dipali Shah