0

I need to create a custom image view for choosing color by design. When user click the circle, inner white circle with a tick should appear, like in example below:

enter image description here

Otherwise, it should be just a circle shape with some color (unchecked state), like below:

enter image description here

The main problem, that I do not know how to create a selector with the inner circle inside and with keeping the ability to setup color programmatically.

Simple rounded shape I can setup, for example, like this:

<de.hdodenhof.circleimageview.CircleImageView
    android:id="@+id/circle_crop"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_gravity="center"
    android:src="@android:color/holo_red_dark" />

How to modify it to setup white circle with tick inside on a checked state (when user click on it)?

Michael Abyzov
  • 452
  • 1
  • 6
  • 16
  • You gonna have to create a custom view. – Onik Dec 22 '20 at 13:35
  • @Onik, I approximately know how to change custom view state/background. My problem is that I don't know how to create a selector for the checked state with the circle inside and ability to change outer circle colour. – Michael Abyzov Dec 22 '20 at 14:11

2 Answers2

1

You need to create a drawable selector for your image view, for example:

drawable_round_view_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/drawable_round_view_selected" android:state_selected="true" />
    <item android:drawable="@drawable/drawable_round_view_unselected" android:state_selected="false" />
    <item android:drawable="@drawable/drawable_round_view_unselected" />
</selector>

drawable_round_view_selected

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape android:shape="oval">
            <size
                android:width="40dp"
                android:height="40dp" />
            <padding
                android:bottom="10dp"
                android:left="10dp"
                android:right="10dp"
                android:top="10dp" />
            <stroke
                android:width="1dp"
                android:color="#3383FF" />
            <solid android:color="#3383FF"/>
        </shape>
    </item>

    <item>
        <shape android:shape="oval">
            <size
                android:width="40dp"
                android:height="40dp" />
            <solid android:color="#ffffff" />
        </shape>
    </item>

    <item android:drawable="@drawable/ic_baseline_check_24" />

</layer-list>

and drawable_round_view_unselected

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <size
        android:width="40dp"
        android:height="40dp" />

    <!-- unselected button background -->
    <solid
        android:color="@color/black" />

    <stroke
        android:color="@color/gray_martini"
        android:width="1dp"/>
</shape>

After that on your layout set the image view like:

 <ImageView
        android:id="@+id/roundImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:src="@drawable/drawable_round_view_selector"/>

Finally on your activity or fragment change view depending on selected state:

binding.roundImageView.setOnClickListener {
            it.isSelected = !it.isSelected
        }

PS: change colors and sizes depending on your requirements.

ziselos
  • 494
  • 5
  • 15
  • your answer is cool, but I need to change solid color of _drawable_round_view_selected_ ( `````` ) programmatically. Is it possible to a little bit modify your code to achieve this effect? – Michael Abyzov Dec 22 '20 at 14:48
  • 1
    Check if this can help you https://stackoverflow.com/a/46655922/7198727 – ziselos Dec 22 '20 at 15:31
1

So easy.

1. Create layer-list Drawable Called "icon_check"

<layer-list 
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item                                           //for the round white background
        android:bottom="10dp"                       //margin, "<size>" tag doesn't work
        android:end="10dp"
        android:start="10dp"
        android:top="10dp">

        <shape 
            android:shape="oval">

            <solid 
                android:color="@color/white" />

        </shape>

    </item>

    <item
        android:drawable="@drawable/check"          //check mark from built-in asset
        android:bottom="14dp"                       //margin, extra 4dp is prefered
        android:end="14dp"
        android:start="14dp"
        android:top="14dp" />

</layer-list>

2. Create selector Drawable Called "foreground_check"

<selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:drawable="@drawable/icon_check"             //layer-list created above
        android:state_selected="true" />

    <item
        android:drawable="@android:color/transparent"       //key point, 【"@null" doesn't work!!】
        android:state_selected="false" />

</selector>

3. Setup CardView

<androidx.cardview.widget.CardView                  //【MaterialCardView doesn't work!!】
    android:id="@+id/cardView"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:foreground="@drawable/foreground_check" //apply layer-list drawable
    app:cardBackgroundColor="@color/black"
    app:cardCornerRadius="20dp" />                  //half of side length

4. Setup Ui Controller

cardView.setOnClickListener {
    it.isSelected = !it.isSelected
}

Result:

enter image description here

Sam Chen
  • 7,597
  • 2
  • 40
  • 73
  • Nice! I want to achieve this effect with background property by a single click (not click with hold). Is it possible? – Michael Abyzov Dec 22 '20 at 19:30
  • @Michael Abyzov It is a single click, I didn't hold, check this full demo: https://youtu.be/QMijeZ2mZUs. Since the check mark is an overlay element (no matter visually or actually), I do not recommend you mix that with the `CardView` or `ImageView` background, if you do so, that means you have to create N `selector` `drawable` for N different color (since the unselected state drawable is set inside the `selector`), is that what you want? – Sam Chen Dec 22 '20 at 20:40
  • I'm sorry for the inattention, it works, like I wanted, and without nested views. Thanks a lot! – Michael Abyzov Dec 22 '20 at 21:09