Bohsen
Bohsen

Reputation: 4350

Android custom view: Delegate attributes to controls inside of view

I have a custom view with three controls inside (an ImageView, a TextInputLayout and a TextInputEditText) and would like to delegate attributes of the xml tags for my custom views to the corresponding views inside of my custom view. Is it possible to have my custom view accept an android:text = "Some string" xml tag and then make it show the string in the corresponding TextInputEditText inside my custom view?

enter image description here

My custom view (InputView.kt):

class InputView(context: Context, attrs: AttributeSet?, @AttrRes defStyleAttr: Int) : ConstraintLayout(context, attrs, defStyleAttr) {

    private lateinit var textInputLayout: TextInputLayout
    private lateinit var textView: TextInputEditText
    private lateinit var imageView: ImageView

//    var drawableRes = imageView.drawable ?: 0
    var text = textView.text
    var hint = textInputLayout.hint
    var error = textInputLayout.error
    var helperText = textInputLayout.helperText
    var ellipsize = textView.ellipsize ?: null

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.custom_inputview, this, true)

        textInputLayout = view.custom_inputview_text_input_layout
        textView = view.custom_inputview_text_input_edit_text
        imageView = view.custom_inputview_image_view

        attrs.let {
            context.theme.obtainStyledAttributes(
                attrs,
                R.styleable.InputView,
                0, 0).apply {

                try {
//                    mShowText = getString(R.styleable.InputView_text)
                } finally {
                    recycle()
                }
            }
        }
    }

}

Layout file for the view (custom_inputview.xml):

<merge
    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="0dp"
    android:layout_height="wrap_content"
    tools:parentTag="com.lucasurbas.masterdetail.ui.persondetails.InputView"
    tools:ignore="ContentDescription">

    <ImageView
        android:id="@+id/custom_inputview_image_view"
        android:layout_width="40dp"
        android:layout_height="40dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:tint="@color/bg_action_mode"
        tools:src="@drawable/ic_vd_hospital_24dp"/>

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/custom_inputview_text_input_layout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp"
        app:layout_constraintBottom_toBottomOf="@+id/custom_inputview_image_view"
        app:layout_constraintStart_toEndOf="@+id/custom_inputview_image_view"
        app:layout_constraintTop_toTopOf="@+id/custom_inputview_image_view">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/custom_inputview_text_input_edit_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:hint="Department"/>

    </com.google.android.material.textfield.TextInputLayout>
</merge>

Upvotes: 1

Views: 1406

Answers (2)

Bohsen
Bohsen

Reputation: 4350

To help others here's my working solution.

class InputView(context: Context, attrs: AttributeSet?, @AttrRes defStyleAttr: Int) : ConstraintLayout(context, attrs, defStyleAttr) {

    private var textInputLayout: TextInputLayout
    private var textView: TextInputEditText
    private var imageView: ImageView

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.custom_inputview, this, true)

        textInputLayout = view.custom_inputview_text_input_layout
        textView = view.custom_inputview_text_input_edit_text
        imageView = view.custom_inputview_image_view

        attrs.let {
            context.theme.obtainStyledAttributes(
                it,
                R.styleable.InputView,
                defStyleAttr, 0).apply {

                try {
                    textView.setText(getText(R.styleable.InputView_android_text))
                    textInputLayout.hint = getText(R.styleable.InputView_android_hint)
                    Log.d("InputView", "attrs " + textView.text)
                } finally {
                    recycle()
                }
            }
        }
    }

}

With the attributes defined in attr.xml:

<declare-styleable name="InputView">
        <attr name="android:text" format="string" />
        <attr name="android:hint" format="string"/>
</declare-styleable>

Upvotes: 1

Chris
Chris

Reputation: 2362

If you want to just use the android style attributes you could do something like the following.

In this example it should pick up the text attribute if you defined it in the xml when creating the InputView.

init {
    attrs?.let {
        val typedArray = context.obtainStyledAttributes(attrs, STYLE_ATTRIBUTES)
        val text = typedArray.getText(0)
        typedArray.recycle()
    }
}

companion object {
    private val STYLE_ATTRIBUTES = intArrayOf(
        android.R.attr.text
    )
}

Upvotes: 1

Related Questions