android – How to make CardView width match it height?-ThrowExceptions

Exception or error:

I have a CardView in a LinearLayout. The Layout reserves 1/5 of the screen for the CardView and 4/5 of the screen for other stuff.

I would like the cardview to be square.

I set the CardView’s height to “match_parent”. But how do I set it’s width to match it’s height?

Am I going to have to create a custom View and use OnMeasure(), or is there a simpler way?

Here is my view’s XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4" >
<!--        Other stuff goes here-->
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <androidx.cardview.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:clickable="true"
            android:foreground="?selectableItemBackground"
            app:cardBackgroundColor="#81C784"
            app:cardCornerRadius="12dp"
            app:cardElevation="3dp"
            app:contentPadding="4dp">

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

                <TextView
                    android:id="@+id/card_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:textColor="#000000"
                    android:textSize="15sp"
                    android:text="TEST"/>

                <TextView
                    android:id="@+id/card_desc"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:textColor="#000000"
                    android:textSize="12sp"
                    android:text="123"/>

                <ImageView
                    android:id="@+id/card_image"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:adjustViewBounds="true"
                    android:padding="3dp"
                    android:scaleType="fitCenter"
                    android:src="@mipmap/ic_launcher"
                    />
            </LinearLayout>
        </androidx.cardview.widget.CardView>
    </LinearLayout>
</LinearLayout>

Here is a screenshot of what, roughly, I would like the cardview to look like:
enter image description here

How to solve:

Well if you are looking for an xml way of achieving this it can be done using ConstraintLayout. You need to make your cardView’s parent layout as constraintlayout instead of LinearLayout, then set constraints and most important part to set

app:layout_constraintDimensionRatio="1:1"

That’s it, you just need to give proper values to height and width and this will ensure it to always maintain a 1:1 aspect ratio.

So your code should look like this

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4" >
        <!--        Other stuff goes here-->
    </LinearLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">


        <!--  match_parent also works, but use 0dp in constraintLayout as below--> 
        <androidx.cardview.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_margin="5dp"
            android:clickable="true"
            android:foreground="?selectableItemBackground"
            app:cardBackgroundColor="#81C784"
            app:cardCornerRadius="12dp"
            app:cardElevation="3dp"
            app:contentPadding="4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="W,1:1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

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

                <TextView
                    android:id="@+id/card_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="TEST"
                    android:textColor="#000000"
                    android:textSize="15sp" />

                <TextView
                    android:id="@+id/card_desc"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="123"
                    android:textColor="#000000"
                    android:textSize="12sp" />

                <ImageView
                    android:id="@+id/card_image"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:adjustViewBounds="true"
                    android:padding="3dp"
                    android:scaleType="fitCenter"
                    android:src="@mipmap/ic_launcher" />
            </LinearLayout>
        </androidx.cardview.widget.CardView>
    </androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

Notice how i used W before 1:1 to show that weight needs to be constrained. based on the height.

This was what the output for above code was

sample output

Another method If you don’t wish to change to constraint layout the other way is to set it programmatically like :

CardView cardView = findViewById(R.id.card_view);
ViewGroup.LayoutParams params = cardView.getLayoutParams();
params.height = params.width;
cardView.setLayoutParams(params);

So choose whichever suits you best.

Leave a Reply

Your email address will not be published. Required fields are marked *