Сделать рябь заполнить весь Просмотр

В моем приложении я хочу создать рябь, заполняющую весь вид. Поскольку он не работает должным образом, я создал минимальное примерное приложение и попробовал его там, но без успеха.

Мой макет выглядит следующим образом:

<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>

И мой drawable определяется следующим образом:

<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>

Здесь - это видео, как оно выглядит в настоящее время. Я хочу, чтобы круг (я думаю, его официально называемый hotspot официально) растет с миддел до тех пор, пока он не заполнит все View. Я не говорю о радиусе пульсации, который здесь сознательно установлен в 0dp. У вас есть идеи, как я могу это достичь?

EDIT: В конце концов, я хочу достичь чего-то вроде this.

Для всех, кто не хочет читать все ответы: мне удалось реализовать его и создать для него repo. Не стесняйтесь использовать это в своем проекте и отправляйте мне запросы на тягу.

Ответ 1

Вы можете добиться этого эффекта, создав свой собственный RippleView. Нарисуйте круг на полном экране с помощью метода onDraw и установите анимацию в этот круг.

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++;
        }

Реализация украдена из проекта RippleEffect Library. Найдите полную реализацию в проекте библиотеки.

Чтобы создать круг только из центра, используйте ниже метод

 /**
     * 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();
    }
}

Выход:

Вы можете получить круг, который растет с середины, пока он не заполнит весь вид введите описание изображения здесь

Ответ 2

Эффект пульсации для доступных просмотров

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);

Кнопки
Изображение кнопки

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>

Использование ?android:colorControlHighlight даст пульсацию того же цвета, что и встроенные ряби в вашем приложении.

Если вам не нравится серый цвет по умолчанию, вы можете указать, какой цвет вам нужен android:colorControlHighlight в вашей теме.

<?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>

Если вы хотите, чтобы пульсация прошла за границей вида, вы можете вместо этого использовать ?attr/selectableItemBackgroundBorderless. Это хорошо работает с ImageButtons и более маленькими кнопками, которые являются частью большого вида:

Ответ 3

Попробуйте это, я надеюсь, что его работа для вас

Использовать android:foreground="@drawable/ripple"

вместо android:background="@drawable/ripple"

а также измените android:radius="0dp" на 50dp или 100dp и проверьте