使波纹填充整个视图

Make ripple fill whole View

在我的应用程序中,我想创建一个充满整个视图的涟漪。因为它不能正常工作,我创建了一个最小的示例应用程序并在那里尝试但没有成功。

我的布局如下所示:

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

Here 是视频目前的样子。我希望圆圈(我认为它被正式称为热点)从中部增长直到填满整个 View。我不是在谈论这里有意设置为 0dp 的波纹半径。您有什么想法可以实现吗?

编辑: 最后我想实现类似 this.

对于不想阅读所有答案的每个人:我设法实现了它并为此创建了一个repo。随意在您的项目中使用它并向我发送请求请求。

您可以通过创建自定义 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();
    }
}

输出:

你可以得到一个从中间增长的圆圈,直到它填满整个视图

可点击视图的连锁反应


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 和属于较大视图一部分的较小按钮:

试试这个,希望对你有用

使用 android:foreground="@drawable/ripple"

而不是 android:background="@drawable/ripple"

并将 android:radius="0dp" 更改为 50dp 或 100dp 并检查