Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin layout width and height binding

I've googled and tried examples but I'm unable to perform binding a FrameLayout width and height. The other bindings work fine.

Final Solution: Example project: https://github.com/jchristof/SimpleDatabindingExample

panel.xml:

<layout>
    <data class="PanelControlBinding">
        <variable
            name="panel"
            type="com.example.viewmodels.ContainerViewModel"/>
    </data>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="@{panel.width}"
        android:layout_height="@{panel.height}"
        android:translationX="@{panel.left}"
        android:translationY="@{panel.top}"
        android:background="@{panel.background}"
        >

    </FrameLayout>
</layout>

binding.kt kotlin file

@BindingAdapter("android:layout_width")
fun setLayoutWidth(view: View, width: Int) {
    val layoutParams = view.layoutParams
    layoutParams.width = width
    view.layoutParams = layoutParams
}

I've tried a number of permutations on the width type (setting it to Float) as well as removing the android: namespace, declaring the setLayoutWidth as a static companion object etc.

I continue to get the error:

Found data binding errors.
****/ data binding error ****msg:Cannot find the setter for attribute 'android:layout_width' with parameter type java.lang.Integer on android.widget.FrameLayout.
file:D:\Projects\strandXmlAppRunner\app\src\main\res\layout\panel.xml
loc:9:32 - 9:42
****\ data binding error ****

How do I need to change these declarations to enable binding on the layout width and height?

Edit

also tried adding an import to the binding adapter:

<data class="PanelControlBinding">
    <import type="com.example.services.BindingKt"/>
    <variable
        name="panel"
        type="com.example.viewmodels.ContainerViewModel"/>
</data>

same error

Edit

going back to my ContainerViewModel, I notice that if I change the return type of width from Int? to Int:

open class ContainerViewModel(val attributes: IValuesStore<String>) {
    val width:Int
        get() = placementArea?.width?.toInt() ?: 0
}

slightly different error:

Found data binding errors.
****/ data binding error ****msg:Cannot find the setter for attribute 'android:layout_width' with parameter type int on android.widget.FrameLayout.
file:D:\Projects\strandXmlAppRunner\app\src\main\res\layout\panel.xml
loc:11:32 - 11:42
****\ data binding error ****

type java.lang.Integer vs type int

Edit

per suggestion, modified to include default values:

<FrameLayout
    android:layout_width="@{panel.width, default=wrap_content}"
    android:layout_height="@{panel.height, default=wrap_content}"
    android:translationX="@{panel.left}"
    android:translationY="@{panel.top}"
    android:background="@{panel.background}"
    >

</FrameLayout>

and

@BindingAdapter("android:layout_width")
fun setLayoutWidth(view: View, width: Float) {
    val layoutParams = view.layoutParams
    layoutParams.width = width.toInt()
    view.layoutParams = layoutParams
}

makes no difference:

Found data binding errors.
****/ data binding error ****msg:Cannot find the setter for attribute 'android:layout_width' with parameter type int on android.widget.FrameLayout.
file:D:\Projects\strandXmlAppRunner\app\src\main\res\layout\panel.xml
loc:11:32 - 11:42
****\ data binding error ****
like image 314
jchristof Avatar asked Jun 03 '18 18:06

jchristof


People also ask

How do you bind a layout?

To convert your XML layouts into the Data Binding layout, follow the below steps: Declare a <layout> tag, which will wrap your existing layout file at the root level. Declare variables under the <data> tag, which will go under the <layout> tag. Declare necessary expressions to bind data inside the view elements.

What is layout width?

Android layout Width & HeightThis property is used to set the width of the given control. According to content the width has been changed. Fill_parent:- fill_parent will take the width according to the container in which we added button. We can also set it in pixel like 200px etc..

Which is the correct way to reference bound data in the XML layout?

Layout Binding expressions Expressions in the XML layout files are assigned to a value of the attribute properties using the “ @{} " syntax. We just need to use the basic syntax @{} in an assignment expression.


1 Answers

To make DataBinding work for layout_width and layout_height, you have to give a default width and height to the view. So what you can do is change xml to something like this:

<layout>
<data class="PanelControlBinding">
    <variable
        name="panel"
        type="com.example.viewmodels.ContainerViewModel"/>
</data>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@{panel.width, default=wrap_content}"
    android:layout_height="@{panel.height, default=wrap_content}"
    android:translationX="@{panel.left}"
    android:translationY="@{panel.top}"
    android:background="@{panel.background}"
    >
</FrameLayout>

And your BindingAdapter like this:

@BindingAdapter("android:layout_width")
fun setLayoutWidth(view: View, width: float) {
val layoutParams = view.layoutParams
layoutParams.width = width
view.layoutParams = layoutParams
}

Try this once, it should work. Let me know if it doesn't work.

EDIT

To make your project work, i have added these things to the build.gradle(Module: app)

1 added apply plugin: 'kotlin-kapt' to the top level plugins.

2 added this to the android tag:

kapt {
    generateStubs = true
}

After these changes, clean and rebuild the project before running.

It will work hopefully.:)

like image 88
Keshav Aggarwal Avatar answered Oct 29 '22 12:10

Keshav Aggarwal