将ImageView放在Button上方 Android

27

我正在尝试使用RelativeLayout将一个ImageView放在一个Button上面。以下是我的xml:

<RelativeLayout
                android:layout_width="0dip"
                android:layout_height="match_parent"
                android:layout_margin="10dp"
                android:layout_weight="0.50" >

                <Button
                    android:id="@+id/btnFindDaysInBetween"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@color/blue_500"
                    android:text="@string/dt_text_days" />

                <ImageView
                    android:id="@+id/imageview_find_days_in_between"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:contentDescription="@string/empty"
                    android:src="@drawable/ic_check_circle_white" />
            </RelativeLayout>

这是图像截图:

输入图片说明

如您所见,ImageView的src图像不可见。但是,如果我将后面的按钮更改为ImageView,则顶部ImageView的图像将可见。请参见下面的代码:

更改后的xml:

 <RelativeLayout
                android:layout_width="0dip"
                android:layout_height="match_parent"
                android:layout_margin="10dp"
                android:layout_weight="0.50" >

                <!-- 
                <Button
                    android:id="@+id/btnFindDaysInBetween"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@color/blue_500"
                    android:text="@string/dt_text_days" />
                -->
                <ImageView
                    android:id="@+id/imageview_find_days"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    android:contentDescription="@string/empty"
                    android:src="@drawable/ic_send_black" />

                <ImageView
                    android:id="@+id/imageview_find_days_in_between"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:contentDescription="@string/empty"
                    android:src="@drawable/ic_check_circle_white" />
            </RelativeLayout>

更改后的XML截图:

在此输入图片描述

我在第一个布局中做错了什么?


使用一个ImageButton和一个TextView来获得所需的结果。 - Skynet
1
为什么不能设置按钮的背景? - Tushar Gogna
@VamsiChalla 你尝试过将“Button”背景设置为透明吗? - Xcihnegn
@Xcihnegn,我不想让按钮透明。我想要一个带有背景的按钮,并将ImageView放在按钮上方。 - Vamsi Challa
我把我的想法转化为答案。 - Xcihnegn
显示剩余3条评论
10个回答

53

原因其实非常简单。:) 我们太过于被2D思维所困扰,而忽视了Z轴上的elevation

你的第一个布局没有问题。只是ButtonImageView高出1dpelevation。因此,无论如何排列这两个视图,Button都会升高。

举个例子

默认情况下,Button使用Widget.Material.Button样式:

<!-- Bordered ink button -->
<style name="Widget.Material.Button">
    <item name="background">@drawable/btn_default_material</item>
    <item name="textAppearance">?attr/textAppearanceButton</item>
    <item name="minHeight">48dip</item>
    <item name="minWidth">88dip</item>
    <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
    <item name="focusable">true</item>
    <item name="clickable">true</item>
    <item name="gravity">center_vertical|center_horizontal</item>
</style>

引入这种高度的属性是 android:stateListAnimatorStateListAnimator 类似于 StateListDrawable,提供状态更改动画。完整的 xml 在这里:Link。但这是按钮的基本状态:

<!-- base state -->
<item android:state_enabled="true">
    <set>
        <objectAnimator android:propertyName="translationZ"
                        android:duration="@integer/button_pressed_animation_duration"
                        android:valueTo="0"
                        android:startDelay="@integer/button_pressed_animation_delay"
                        android:valueType="floatType"/>
        <objectAnimator android:propertyName="elevation"
                        android:duration="0"
                        android:valueTo="@dimen/button_elevation_material"
                        android:valueType="floatType" />
    </set>
</item>

正如您所看到的,按钮的高程值被设置为@dimen/button_elevation_material

<dimen name="button_elevation_material">1dp</dimen>

这就是为什么ImageView最终出现在Button后面/下面的原因。

那么我们该怎么办呢?

一种简单直接的解决方案是将ImageView的高度设置为相同的值 - 1dp

另一种解决方案,需要花费一些时间精力,是移除Button的高度而不是改变ImageView的高度。基于默认的StateListAnimator,我们可以创建自己的动画并移除高度。然后,在您的res/values-v21/styles.xml中,定义一个从Widget.Material.Button继承的样式:

<style name="MyDepressedButtonStyle" parent="android:Widget.Material.Button">
    <item name="android:stateListAnimator">@anim/customized_state_animator</item>
</style>

现在,将这个样式设置到你的Button中:

<Button
    style="@style/MyDepressedButtonStyle"
    ....
    .... />

编辑:

实际上,我们可以直接应用自定义的StateListAnimator

<Button
    android:stateListAnimator="@anim/customized_state_animator"
    ....
    .... />

不需要走风景线!


1
“elevation” 仅适用于 Api 21 及更高版本,因此您无法使用“直接”方法。 - Bron Davies
1
@BronDavies 这整个问题都是关于API版本21及以上的,所以我不确定你的意思是什么。 - Vikram
1
我不得不将我的高度设置为2dp,以使我的视图重叠在我的按钮上方,但解释很好! - Hellojeffy
我应该在 @anim/customized_state_animator 中放什么? - DJTano
1
请查看我的gist,基于这个答案。@DJTano https://gist.github.com/mwshubham/8e1012e2fdf05b618abd5bba5b72e34c#file-customized_state_animator-xml - Shubham AgaRwal
感谢提供这个证明。我之前很困惑发生了什么。 - M.kazem Akhgary

28

我找到了一个解决方法: 只需 android:elevation="2dp"

<Button
        android:id="@+id/btnAccess"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_gravity="right|center"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp"/>

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView4"
        android:background="@drawable/or"
        android:layout_alignBottom="@+id/btnRegister"
        android:layout_centerHorizontal="true"
        android:layout_margin="5dp"
        android:elevation="2dp" />

2
适用于API级别21+。 - fnc12
我还必须添加翻译Z。 - Adam Johns

4

谢谢。当点击按钮时,提升ImageView并不能起到作用,但这个方法很好地解决了问题。 - omikes

3

使用 ImageButton 替换 Button,并将 ImageButton 背景设置为透明。

<ImageButton
    android:id="@+id/btnFindDaysInBetween"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/blue_500_text"
    android:background="@android:color/transparent"  
    />

<ImageView
    android:id="@+id/imageview_find_days_in_between"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:contentDescription="@string/empty"
    android:src="@drawable/ic_check_circle_white" />

你可以制作一个带有"blue_500"颜色和文本的图像(这很容易创建),然后将此图像设置为你的ImageButton。之后,你的ImageView会出现在ImageButton的顶部。
希望这能帮到你!

3

按钮只是应用了某种样式的TextView,因此如果您用TextView替换Button,则可以在其上方显示ImageView。这在API<21上也适用。


1
在我看来,这是最有价值的答案,因为你甚至可以将 onClickListener() 设置到 textView 上,使其像一个按钮一样工作。 - Frank Eno

2

@Vamsi,我尝试了你的两种组合,第一种在Button上无法使用。你需要采用ImageView。以下是我使用ImageView的尝试结果:

enter image description here

当我尝试使用Button时,结果如下:

enter image description here

我尝试改变顺序,但都无济于事!看来你只能采用ImageViewImageButton

最后,你可以看到我的尝试:

<RelativeLayout 
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <!-- <ImageView
        android:id="@+id/btnTest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher_web"
        android:contentDescription="@string/app_name"
        android:text="@string/app_name" /> -->

    <ImageView
        android:layout_width="wrap_content"
        android:id="@+id/imgView"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:contentDescription="@string/app_name"
        android:src="@drawable/ic_launcher" />

    <Button
        android:id="@+id/btnTest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/imgView"
        android:layout_alignTop="@+id/imgView"
        android:text="@string/app_name" />

</RelativeLayout>

我之前也用过ImageViewImageButton来完成相同的工作(可能是用ImageView),并尝试了与你尝试Button时相同的方法。

谢谢。


是的..看起来按钮会在顶部..我还在寻找一个明确的答案..谢谢你的时间。 - Vamsi Challa
没问题!总是最好等待一些好的解决方案,而不是搞乱你的代码 :) - Faizan Mubasher

2

android:background属性适用于所有视图。顾名思义,它是背景。

android:src属性适用于ImageViews及其子类。你可以将其视为前景。因为ImageView是View的子类,所以你甚至可以在其中使用android:background属性。

如果前景比背景小,则未被前景覆盖的背景部分将可见。此外,您可以在前景中使用透明度,这样背景就会透明可见。您可以将BACKGROUND用于所有视图。但是,您只能将SRC用于ImageViewImageButton


我理解你关于ImageView和ImageButton的android:src的说法,但是在第一个布局中为什么ImageView不可见呢? - Vamsi Challa
我已经检查了你的XML文件,并且在我的端上它是可以工作的。ic_check_circle_white的格式是什么? - Ameer

0
如果您想在Android API<21(例如,KitKat = 19)上获取一个ImageView放在Button的顶部,最简单的方法是根本不使用Button,而是使用2个ImageView。为什么要这样做?可能是因为您定义了一个可绘制形状来使按钮看起来更“酷”,因此您已经在该形状中使用了android:background。
示例:
<Button
    android:id="@+id/button01"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/buttonshape"
    />

<ImageView
    android:id="@+id/image01"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:layout_marginTop="10dp"
    android:layout_marginStart="10dp"
    android:src="@drawable/desiredImageOnTop"
    />

其中 @drawable/buttonshape.xml 是:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
<corners
    android:radius="30dp"
    />
<gradient
    android:angle="45"
    android:centerColor="#47A891"
    android:centerX="35%"
    android:endColor="#000000"
    android:startColor="#E8E8E8"
    android:type="linear"
    />
<padding
    android:bottom="0dp"
    android:left="0dp"
    android:right="0dp"
    android:top="0dp"
    />
<size
    android:width="100dp"
    android:height="100dp"
    />
<stroke
    android:width="3dp"
    android:color="#878787"
    />
</shape>

在这种情况下,您应该将Button替换为ImageView,将android:background更改为android:src,然后在Java代码中,您只需添加一个OnClickListener,就像它是一个Button一样(两个控件都派生自View,并且OnClickListener是一个View事件)。非常好用!

0

实际上,这不是一个错误,而是一个简单的设计问题。我已经在处理它了两个小时,最终找到了一个简单的方法。现在,我想分享代码。

<FrameLayout
            android:layout_alignParentStart="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >

                <androidx.appcompat.widget.AppCompatButton
                
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginTop="4dp"
                    android:background="@drawable/custom_button"
                    android:paddingLeft="33dp"
                    android:layout_marginStart="33dp"
                    android:text="CHECK APPOINTMENT"
                    android:textAlignment="viewEnd"
                    android:textSize="18sp"

                    />

            </LinearLayout>


            <androidx.cardview.widget.CardView
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                app:cardCornerRadius="40dp">

                <ImageView
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:elevation="2dp"
                    android:src="@drawable/care_logo"
                    android:scaleType="fitCenter"
                    />
            </androidx.cardview.widget.CardView>

        </FrameLayout>

它正在运行。


-2
我在一个RelativeLayout中使用了ImageView放置在Button上,希望这可以帮到你。
 <RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <View
        android:id="@+id/tempview"
        android:layout_width="0dp"
        android:layout_height="0dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tempview"
        android:background="@drawable/ic_launcher" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tempview"
        android:src="@drawable/img_cancel" />
</RelativeLayout>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接