How to create a RadioButton custom view?

76 Views Asked by At

I've tried many tutorials and solutions on internet but couldn't make mine work. Basically I want a layout like this to work as 7 RadioButtons:

RadioButtons

I have my CustomRadioButton class that I want it to behave like a RadioButton, to be used inside a normal RadioGroup. That's why I'm extending AppCompatRadioButton.

The problem is that I can't inflate my LayoutWeekDayBinding because the parent is not a ViewGroup. It gives me this error message: Type mismatch. Required: ViewGroup? Found: CustomRadioButton

class CustomRadioButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatRadioButton(context, attrs, defStyleAttr) {

    private lateinit var binding: LayoutWeekDayBinding

    var weekDay: String = ""
        get() = field
        set(value) {
            binding.textWeekDay.text = value
            field = value
        }

    init {
        initView(context)
    }

    private fun initView(context: Context) {
        binding = LayoutWeekDayBinding.inflate(LayoutInflater.from(context), this, true)
        // error in this keyword above
    }
}

My layout_week_day.xml is like this:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_week_day_id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true">

    <TextView
        android:id="@+id/textWeekDay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:fontFamily="@font/montserrat_medium"
        android:textColor="@color/brownish_grey"
        android:textSize="14sp"
        android:textStyle="normal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textWeekTemperature"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/montserrat_regular"
        android:textColor="@color/brownish_grey"
        android:textSize="14sp"
        android:textStyle="normal"
        app:layout_constraintEnd_toEndOf="@+id/textWeekDay"
        app:layout_constraintStart_toStartOf="@+id/textWeekDay"
        app:layout_constraintTop_toBottomOf="@+id/textWeekDay" />
</androidx.constraintlayout.widget.ConstraintLayout>

I did tried other "inflate" methods but none of them worked:

private fun initView(context: Context) {
    binding = LayoutWeekDayBinding.inflate(LayoutInflater.from(context))

    val view = LayoutInflater.from(context).inflate(R.layout.layout_week_day, null)
    binding = LayoutWeekDayBinding.bind(view)
}

What am I missing here?

2

There are 2 best solutions below

0
android developer On

The builder is correct. You call:

binding = LayoutWeekDayBinding.inflate(LayoutInflater.from(context), this, true)

And "this" is your class that extends from AppCompatRadioButton (CustomRadioButton), yet AppCompatRadioButton doesn't extend ViewGroup at all. The order is:

java.lang.Object
   ↳    android.view.View
       ↳    android.widget.TextView
           ↳    android.widget.Button
               ↳    android.widget.CompoundButton
                   ↳    android.widget.RadioButton
                       ↳    androidx.appcompat.widget.AppCompatRadioButton

https://developer.android.com/reference/androidx/appcompat/widget/AppCompatRadioButton

So, you can't use AppCompatRadioButton and change its content. It's a button. It can't contain other Views of your choice.

What you can do is to implement a similar View that works the same, and as a RadioButton is very simple to do, it shouldn't take long at all. Extend from FrameLayout or some other ViewGroup, and remember its state. You need to also turn off the others in your own alternative to RadioGroup

0
Frosty On

It looks like you're passing your custom class as the container to its own layout. Removing this from your inflate() call should fix your error.

You also don’t need to add the inflated view to itself, when you create the instance it will inflate itself and you can add it to your view group.

private fun initView(context: Context) {
    binding = LayoutWeekDayBinding.inflate(context.layoutInflater, this, false)
}