7

I'm trying to bind the width and height of my view but I can't see where's the problem.

I found this on this google issue

To implement these for your application, create a binding adapter:

@BindingAdapter("android:layout_width")
public static void setLayoutWidth(View view, int width) {
  LayoutParams layoutParams = view.getLayoutParams();
  layoutParams.width = width;
  view.setLayoutParams(layoutParams);
}

So I created my Binding Adapter like this :

public class SimpleBindingAdapter {

    @BindingAdapter("android:layout_width")
    public static void setLayoutWidth(View view, int width) {
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        layoutParams.width = width;
        view.setLayoutParams(layoutParams);
    }

    @BindingAdapter("android:layout_height")
    public static void setLayoutHeight(View view, int height) {
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        layoutParams.height = height;
        view.setLayoutParams(layoutParams);
    }

    //Others methods...
}

And then try to set my width and height like this :

<View
        android:layout_width="@{paramsMessage.width}"
        android:layout_height="@{paramsMessage.height}"
... />

Where paramsMessage.width is a public int attribute.

But I get this error :

Caused by: java.lang.RuntimeException: Binary XML file line #25: You must supply a layout_width attribute. at android.content.res.TypedArray.getLayoutDimension(TypedArray.java:607) at android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.java:6761) at android.view.ViewGroup$MarginLayoutParams.(ViewGroup.java:6930) at android.widget.RelativeLayout$LayoutParams.(RelativeLayout.java:1244) at android.widget.RelativeLayout.generateLayoutParams(RelativeLayout.java:1084) at android.widget.RelativeLayout.generateLayoutParams(RelativeLayout.java:83) at android.view.LayoutInflater.rInflate(LayoutInflater.java:820) at android.view.LayoutInflater.inflate(LayoutInflater.java:511) at android.view.LayoutInflater.inflate(LayoutInflater.java:415) at android.databinding.DataBindingUtil.inflate(DataBindingUtil.java:116) at android.databinding.DataBindingUtil.inflate(DataBindingUtil.java:88) at be.standard.appbusiness.tutorials.home.TutorialHomeFragment.onCreateDialog(TutorialHomeFragment.java:35) at android.support.v4.app.DialogFragment.getLayoutInflater(DialogFragment.java:308) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613) at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:330) at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1234) at android.app.Activity.performStart(Activity.java:6258) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2621) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723)  at android.app.ActivityThread.access$900(ActivityThread.java:172)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:145)  at android.app.ActivityThread.main(ActivityThread.java:5832)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

  I would appreciate any helps on this, thank you !

4

4 回答 4

5

这已经很晚了,但对于任何需要它的人,我做了以下事情:

我在视图中将 layout_width 和 layout_height 设置为 0dp。

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp" />

您可以将 minWidth / minHeight 与数据绑定一起使用,或者创建自己的属性以通过绑定设置宽度和高度。

<ImageView
     android:layout_width="0dp"
     android:layout_height="0dp"
     android:minWidth="@{controller.getDeviceWidthDP()}"
     android:minHeight="@{controller.getDeviceWidthDP()}" />

为每个属性创建 BindingAdapter,这里我使用 Kotlin。

object ViewBindings{
    @JvmStatic
    @BindingAdapter("android:minWidth")
    fun setLayoutWidth(view: View, width: Float) {
        val layoutParams = view.layoutParams
        layoutParams.width = (width * view.resources.displayMetrics.density).toInt()
        view.layoutParams = layoutParams
        view.invalidate()
    }

    @JvmStatic
    @BindingAdapter("android:minHeight")
    fun setLayoutHeight(view: View, height: Float) {
        val layoutParams = view.layoutParams
        layoutParams.height = (height * view.resources.displayMetrics.density).toInt()
        view.layoutParams = layoutParams
        view.invalidate()
    }
}

在这个例子中,我使用了一个扩展函数来获取设备的宽度和高度尺寸。

fun Context.getDeviceDimensions(): Pair<Float, Float> {
    var widthHeight = Pair(0.0F, 0.0F)
    resources.displayMetrics.let {
        val dpHeight = it.heightPixels / it.density
        val dpWidth = it.widthPixels / it.density
        widthHeight = Pair(dpWidth, dpHeight)
    }

    return widthHeight
}

我创建了一个控制器类并使用<data>标签将其包含在我的布局中。

class SomeController(val someFragment: SomeFragment){
    fun getDeviceWidthDP(): Float{
        val width = someFragment.context.getDeviceDimensions().first
        return width
    }
}
于 2017-04-03T21:28:02.027 回答
1

layout_width您可以通过在 xml 中为和layout_height属性设置默认值来防止崩溃。

<View
        android:layout_width="@{paramsMessage.width, default=@dimen/default_width}"
        android:layout_height="@{paramsMessage.height, default=@dimen/default_height}"
... />
于 2020-10-22T23:36:10.240 回答
0

我认为问题不在于数据绑定。layout_width并且layout_height是应该在膨胀时间给出的属性,除非你会遇到这个崩溃。BindingAdapter的方法在视图已经膨胀之后被调用,这为时已晚:(

于 2016-07-25T13:03:24.293 回答
-2

绑定适配器方法必须在您作为数据传递的类中,在您的情况下,代码必须在此对象 paramsMessage 的类中

于 2016-01-15T06:30:43.547 回答