将 imageButton 裁剪成背景的形状 android

Crop imageButton in the shape of the background android

正如您在图片中看到的,ImageButton 具有“设置图标”的背景,但它被认为是一个矩形。我希望它被裁剪成图标的形状,这样涟漪效应只会出现在图标本身上,并且不会在图标边界之外继续(如 this tutorial (第四个 Ex),但使用自定义形状).
(使用 elevation 会出现同样的问题,这会使阴影成为矩形而不是围绕背景)。
我怎样才能实现它?

我的代码:

  <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  tools:context=".MainActivity">

  <ImageButton
        android:id="@+id/button"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginStart="30dp"
        android:layout_marginBottom="30dp"
        android:outlineProvider="background"

        android:background="@drawable/ic_settings_black_24dp"
        android:backgroundTint="#c0c0c0"
        app:layout_constraintBottom_toBottomOf="parent"
        android:foreground="?attr/selectableItemBackground"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

ic_settings_black_24dp.xml(来自 Vector Asset Studio):

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"

        android:viewportHeight="24">
    <path
        android:fillColor="#fff"
        android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>
</vector>

TIA

经过一些尝试,我想我得到了你要求的效果。

首先,我们需要通过在 drawable 目录中创建一个新文件来定义自定义波纹效果。我将其命名为 ripple_ic_settings:

<?xml version="1.0" encoding="utf-8"?>
<!-- The color here is the color of the ripple effect. I set it to teal to see the effect better. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/teal_700"
    android:exitFadeDuration="@android:integer/config_shortAnimTime">
    <!-- The drawable must be set to your vector icon. In this case the settings icon -->
    <item android:id="@android:id/mask" android:drawable="@drawable/ic_settings_black_24dp">
        <!-- The shape of the ripple effect -->
        <shape android:shape="oval">
            <corners android:radius="3dp"/>
            <solid android:color="@android:color/white"/>
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <!-- Color is set to transparent so we dont see the background -->
            <solid android:color="@android:color/transparent"/>
        </shape>
    </item>
</ripple>

在第一个 item 条目上,我们将 android:drawable 属性设置为可绘制的矢量图标。您可以将其设置为您喜欢的任何矢量图标,但请记住,您需要为要在应用中使用的每个图标创建此自定义波纹效果。

比起我这样修改你的ic_settings_black_24dp.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"

    android:viewportHeight="24">
    <!-- fillColor is the color that you want for your icon -->
    <path
        android:fillColor="#c0c0c0"
        android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>

</vector>

我只将 path 上的 fillColor 属性更改为您在 ImageButton 中设置 backgroundTint 的颜色。

最后,我将您布局中的 ImageButton 更改为以下内容:

<ImageButton
        android:id="@+id/button"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginStart="30dp"
        android:layout_marginBottom="30dp"
        android:background="@drawable/ic_settings_black_24dp"
        android:foreground="@drawable/ripple_ic_settings"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

此处重要的是将 android:background 设置为图标(在本例中为 @drawable/ic_settings_black_24dp),将 android:foreground 设置为自定义波纹效果(@drawable/ripple_ic_settings ).

您可以将矢量设置为涟漪效果资源中的项目

ic_settings_black_24dp.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#c0c0c0"
        android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>

</vector>

您可以在这里设置波纹效果颜色
ripple_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#fff000" // set Color of ripple effect
    android:exitFadeDuration="500">
    <item android:drawable="@drawable/ic_settings_black_24dp" />
</ripple>

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageButton
        android:id="@+id/button"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginStart="30dp"
        android:layout_marginBottom="30dp"
        android:background="@drawable/ic_settings_black_24dp"
        android:foreground="@drawable/ripple_settings"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

您可以自定义按钮,在 drawables 文件夹中创建一个选择器。我的名字叫 button.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_enabled="false"
        android:drawable="@drawable/button_disabled" />
    <item
        android:state_pressed="true"
        android:state_enabled="true"
        android:drawable="@drawable/button_pressed" />
    <item
        android:state_enabled="true"
        android:drawable="@drawable/button_enabled" />
</selector>

您显然必须通过简单地更改设置按钮的颜色或透明度来创建按钮的不同实例,即您必须创建 button_disabled.xmlbutton_pressed.xmlbutton_enabled.xml。然后你可以将 button.xml 传递给你的 imageButton 背景 属性

android:background="@drawable/button"

它应该可以工作。

然后是 lazy 选项 ;) 如果您确实喜欢按钮的背景阴影动画,但只是对其投射到的丑陋正方形感到厌烦,我建议您尝试为您的按钮输出以下代码:

 <ImageButton
        android:id="@+id/button"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginStart="30dp"
        android:layout_marginBottom="30dp"
        android:src="@drawable/ic_settings_black_24dp"  //<---THIS IS KEY
        android:background="?attr/selectableItemBackgroundBorderless" //<-- THIS IS KEY
        android:backgroundTint="#c0c0c0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />