Search code examples
androidxmlselectorcardview

How to change the border color of CardView by first clicking and again change back to previous color on Second click Android?


How to do it using selector instead of changing background?

if(isSelected) {
                binding.cvStainMaster.setBcackgroundResource(R.drawable.boarder_blue_corner);
                binding.btnStart.setBackgroundResource(R.drawable.bg_button_primary);
                isSelected = false;
            }else{
                binding.cvStainMaster.setBackgroundColor(Color.WHITE);
                binding.btnStart.setBackgroundResource(R.drawable.button_background_with_corner);
                isSelected = true;
            }

I have done it by changing background. but I want it to do using selector


Solution

  • Using the androidx.cardview.widget.CardView there is no any property to change the border/stroke colour but you can achieve it using the com.google.android.material.card.MaterialCardView from Material Design Library which is a subclass of androidx.cardview.widget.CardView (MaterialCardView extends CardView).

    To add the MaterialCardView in your project first you have to add the grandle depedency of Material Design Library pointing to the latest version like: implementation 'com.google.android.material:material:1.5.0' and your app Theme must inherit from Theme.MaterialComponents.*.

    Now with MaterialCardView you can use the app:strokeColor attribute to set the stroke/border color pointing to a color selector to change the border color based on the card checked/unchecked state and the app:strokeWidth to set the stroke width. To activate the android:state_checked=true/false states you have to add also the attribute android:checkable="true" and with app:checkedIconSize="0dp" you can remove the default checked-stated icon. Below is an example usage:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    
        <com.google.android.material.card.MaterialCardView
            android:id="@+id/materialCardView"
            android:layout_width="80dp"
            android:layout_height="100dp"
            android:checkable="true"
            app:cardBackgroundColor="@android:color/holo_green_light"
            app:cardForegroundColor="@android:color/transparent"
            app:checkedIconSize="0dp"
            app:cardCornerRadius="10dp"
            app:cardElevation="2dp"
            app:strokeWidth="4dp"
            app:strokeColor="@color/card_border_selector"/>
    
    </RelativeLayout>
    

    where the @color/card_border_selector is defined in the res/color/card_border_selector.xml like the below:

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@android:color/holo_orange_light" android:state_checked="true"/>
        <item android:color="@android:color/holo_blue_light" android:state_checked="false"/>
    </selector>
    

    And programmatically every time you click on the MaterialCardView you have to change the state using the materialCardView.setChecked() function like the below example:

    MaterialCardView materialCardView = findViewById(R.id.materialCardView);
    materialCardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            materialCardView.setChecked(!materialCardView.isChecked());
        }
    });
    

    Result for android:state_checked=false:

    unselected_state

    Result for android:state_checked=true:

    selected_state