Android, создайте округлый настраиваемый вид с проверенными и непроверенными случаями

Мне нужно создать собственный вид изображения для выбора цвета по дизайну. Когда пользователь нажимает на круг, должен появиться внутренний белый круг с галочкой, как в примере ниже:

В противном случае это должен быть просто круг с некоторым цветом (непроверенное состояние), как показано ниже:

Основная проблема в том, что я не знаю, как создать селектор с внутренним кругом внутри и с возможностью программной настройки цвета.

Простую округлую форму я могу настроить, например, так:

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

Как изменить его, чтобы установить белый круг с галочкой внутри в отмеченном состоянии (когда пользователь нажимает на него)?

Вам нужно будет создать собственное представление.

Onik 22.12.2020 14:35

@Onik, я примерно знаю, как изменить пользовательское состояние просмотра / фон. Моя проблема в том, что я не знаю, как создать селектор для проверенного состояния с кругом внутри и возможностью изменить цвет внешнего круга.

Michael Abyzov 22.12.2020 15:11
0
2
331
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно создать селектор для рисования для вашего изображения, например:

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>

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

После этого на вашем макете установите вид изображения, например:

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

Наконец, в вашей активности или представлении изменения фрагмента в зависимости от выбранного состояния:

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

PS: меняйте цвета и размеры в зависимости от ваших требований.

ваш ответ классный, но мне нужно программно изменить сплошной цвет drawable_round_view_selected ( <solid android:color = "#3383FF"/> ). Можно ли немного изменить код для достижения такого эффекта?

Michael Abyzov 22.12.2020 15:48

Проверьте, может ли это вам помочь stackoverflow.com/a/46655922/7198727

ziselos 22.12.2020 16:31
Ответ принят как подходящий

Так легко.

1. Создайте layer-listDrawable под названием "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. Создайте selectorDrawable под названием "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. Настройка 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. Настройка пользовательского интерфейса

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

Результат:

Хороший! Я хочу добиться этого эффекта с помощью свойства фона одним щелчком мыши (а не щелчком с удержанием). Является ли это возможным?

Michael Abyzov 22.12.2020 20:30

@Michael Abyzov Это один щелчок, я не удержался, посмотрите это полное демо: youtu.be/QMijeZ2mZUs. Поскольку галочка является элементом наложения (независимо от того, визуально это или фактически), я не рекомендую вам смешивать это с фоном CardView или ImageView, если вы это сделаете, это означает, что вам нужно создать N selectordrawable для N разных цветов (поскольку невыбранное состояние, доступное для рисования, установлено внутри selector), это то, что вы хотите?

Sam Chen 22.12.2020 21:40

Прошу прощения за невнимательность, работает, как я и хотел, и без вложенных представлений. Большое спасибо!

Michael Abyzov 22.12.2020 22:09

Другие вопросы по теме