Vamsi Challa
Vamsi Challa

Reputation: 11109

Place ImageView over Button android

I am trying to place an ImageView over a Button using RelativeLayout. Here is my 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>

Here is the image screenshot:

enter image description here

As you can see, the ImageView's src image is not visible. However if i change the button at the back to an ImageView, the image of the top ImageView is visible. Please refer below..

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

Changed xml's screenshot:

enter image description here

What is it that i am doing wrong in the first layout?

Upvotes: 27

Views: 23781

Answers (10)

SUSMITA BHATTACHARYA
SUSMITA BHATTACHARYA

Reputation: 21

Actually, This is not an error, it is a simple design issues. I have been working on it for last 2 hours. And at last get an easy way. Now, I want to share the code.

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

It is working.

Upvotes: 0

Adri&#225;n Alvarez
Adri&#225;n Alvarez

Reputation: 431

If you want to get an ImageView on top of a Button, and you are developing for Android API < 21 (for instance, KitKat = 19), the easiest way is to not use a Button at all and use 2 ImageView instead. Why would you want to do that? May be because you defined a drawable shape to make the button look "cooler", so you are already using android:background with that shape.

Ex:

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

Where @drawable/buttonshape.xml is:

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

In that case, you should replace the Button with an ImageView, change android:background to android:src, and then, in the java code, you just add an OnClickListener as if it was a Button (both controls derive from View, and OnClickListener is a View event). Works like a charm!

Upvotes: 0

anon
anon

Reputation:

Button is just a TextView with a certain style applied to it, so if you replace Button with TextView you can display an ImageView on top of it. This also works on API < 21.

Upvotes: 3

DJTano
DJTano

Reputation: 1424

Actually it's much easier to just set the StateListAnimator to @null

<Button
    ...
    android:stateListAnimator="@null" />

Source Android 5.0 android:elevation Works for View, but not Button?

Upvotes: 4

AeonDave
AeonDave

Reputation: 791

I found a solution: simply 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" />

Upvotes: 29

Vikram
Vikram

Reputation: 51581

The reason is actually very simple. :) We are so caught up thinking in 2D that we overlook the elevation - in Z.

There is nothing wrong with your first layout. The Button simply has a higher elevation than the ImageView - exactly 1dp higher. Therefore, no matter how you arrange the two views, the Button rises above.

A bit of proof:

A Button, by default gets the Widget.Material.Button style:

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

The attribute that introduces this elevation is android:stateListAnimator. StateListAnimator is similar to StateListDrawable, and provides state change animations. The complete xml is here: Link. But here's the base state of the button:

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

As you can see, the elevation value for the button is set to @dimen/button_elevation_material:

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

And that's how the ImageView ends up being behind/below the Button.

So, what can we do?

A straight-forward solution would be to set the ImageView's elevation to the same amount - 1dp.

Another solution, which will require a bit of work, is to remove the Button's elevation rather than change ImageView's. Based on the default StateListAnimator, we can create our own - and remove the elevation. Then, in your res/values-v21/styles.xml, define a style that inherits from Widget.Material.Button:

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

Now, set this style on your Button:

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

Edit:

Actually, we can apply the customized StateListAnimator directly:

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

No need to take the scenic route!

Upvotes: 53

Nanites
Nanites

Reputation: 411

I placed ImageView on a Button with a diversion of RelativeLayout, hope this helps.

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

Upvotes: -2

Xcihnegn
Xcihnegn

Reputation: 11597

Use ImageButton replace Button and set ImageButton background as transparent.

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

You can make a image that has your blue_500 color and text(that is easy to create), then set this image to your ImageButton. After that, your ImageView will see on the top of ImageButton.

Hope this help!

Upvotes: 3

Faizan Mubasher
Faizan Mubasher

Reputation: 4569

@Vamsi I tried your both combinations and first one is not working with Button. You have to go through ImageView. This is what I tried with with ImageView:

enter image description here

While I tried to do it with Button and see what was result:

enter image description here

I tried to change the order but all in vain! It seems you have to go with either ImageView or ImageButton.

At the end! You can see what I had tried:

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

I had done same kind of work either with ImageView or ImageButton (probably with ImageView) and tried same approach as you were trying with Button.

Thanks

Upvotes: 2

Ameer
Ameer

Reputation: 2769

android:background exists for all the view. As the name suggests this is what is going to be there in the background.

android:src exists for ImageViews and its subclasses. You can think of this as the foreground. Because ImageView is a subclass of View you even have android:background for that.

If the foreground is smaller than background, the background portion which is not covered by the foreground would be visible. Also, you can use transparency in the foreground in which case the background would be visible(transparently). You can use BACKGROUND FOR ALL THE VIEWS.. But You can use SRC only for ImageView & ImageButton.....

Upvotes: 2

Related Questions