Position button on top-end of CardView

1.3k Views Asked by At

enter image description here

How can I add a button on top-end of CardView? I have a solution but I don't like set a fixed height (ie 50dp) of button and than set margin_top (ie 25dp) of card_view. Do you have other solutions?

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.cardview.widget.CardView
    android:id="@+id/card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="25dp"
    android:clickable="true"
    android:focusable="true"
    android:foreground="?android:attr/selectableItemBackground"
    app:cardCornerRadius="@dimen/corner_radius"
    app:cardElevation="2dp"
    app:cardUseCompatPadding="true"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@id/btn">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <View
            android:id="@+id/view_cover"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#ddd"
            app:layout_constraintDimensionRatio="16:9"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

<com.google.android.material.button.MaterialButton
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="50dp"
    android:layout_marginEnd="@dimen/dimen_16"
    android:elevation="@dimen/dimen_2"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2

There are 2 best solutions below

3
Hiro On

Looks like constraint layout doesn't allow negative margin(offset), so all you can do is workarounds.

There is another workaround, which i think is better than your example in terms of "intention". It goes like this:

Assuming your button is 50dp width/height.

  1. Place Space element inside the constraint layout. Let's say width/height is 25dp(half of 50dp).
  2. Align the Space element to the corner of the constraint layout. In case you want to put the button top end, then top of Space to top of constraint layout, and end of Space to end of constraint layout.

At this point, you virtually created "anchor" points where you can align other elements to, that is, the bottom and start of Space.

  1. Align the start of the button to the start of Space, and the bottom of the button to the bottom of Space.

The button is now placed as if you would do layout_marginEnd/layout_marginBottom of -25dp.

The reason I think this is better is that the overlapping detail is no longer the constraint layout's concern, instead, it's the button and its neighboring element's.

1
Bhavin On

You can do it like following

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".fragments.LibraryFragment">

    <androidx.cardview.widget.CardView
        android:id="@+id/my_card"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        />


    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@android:drawable/ic_delete"
        app:layout_constraintWidth_percent="0.08"
        app:layout_constraintDimensionRatio="1:1"
        app:tint="@color/redColor"
        android:elevation="50dp"
        app:layout_constraintTop_toTopOf="@id/my_card"
        app:layout_constraintBottom_toTopOf="@id/my_card"
        app:layout_constraintStart_toStartOf="@id/my_card"
        app:layout_constraintEnd_toEndOf="@id/my_card"
        app:layout_constraintHorizontal_bias="0.98"
        />
</androidx.constraintlayout.widget.ConstraintLayout>

This will generate output like this enter image description here

the image size will be based on the width of the screen which will be differ from device to device and it will resize according to it. and also it will be square due to we provided the ratio as 1:1