【问题标题】:Android DataBinding layout_width : You must supply a layout_width attributAndroid DataBinding layout_width :您必须提供 layout_width 属性
【发布时间】:2016-04-18 14:55:11
【问题描述】:

我正在尝试绑定视图的宽度和高度,但我看不出问题出在哪里。

我在this google issue找到了这个

要为您的应用程序实现这些,请创建一个绑定适配器:

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

所以我像这样创建了我的绑定适配器:

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...
}

然后尝试像这样设置我的宽度和高度:

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

其中 paramsMessage.width 是公共 int 属性。

但我收到此错误:

引起:java.lang.RuntimeException:二进制 XML 文件第 25 行:您 必须提供 layout_width 属性。 在 android.content.res.TypedArray.getLayoutDimension(TypedArray.java:607) 在 android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.java:6761) 在 android.view.ViewGroup$MarginLayoutParams.(ViewGroup.java:6930) 在 android.widget.RelativeLayout$LayoutParams.(RelativeLayout.java:1244) 在 android.widget.RelativeLayout.generateLayoutParams(RelativeLayout.java:1084) 在 android.widget.RelativeLayout.generateLayoutParams(RelativeLayout.java:83) 在 android.view.LayoutInflater.rInflate(LayoutInflater.java:820) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:511) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:415) 在 android.databinding.DataBindingUtil.inflate(DataBindingUtil.java:116) 在 android.databinding.DataBindingUtil.inflate(DataBindingUtil.java:88) 在 be.standard.appbusiness.tutorials.home.TutorialHomeFragment.onCreateDialog(TutorialHomeFragment.java:35) 在 android.support.v4.app.DialogFragment.getLayoutInflater(DialogFragment.java:308) 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248) 在 android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738) 在 android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613) 在 android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:330) 在 android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547) 在 android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1234) 在 android.app.Activity.performStart(Activity.java:6258) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2621) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723) 在 android.app.ActivityThread.access$900(ActivityThread.java:172) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:145) 在 android.app.ActivityThread.main(ActivityThread.java:5832) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

我将不胜感激任何帮助,谢谢!

【问题讨论】:

    标签: android android-layout width android-databinding


    【解决方案1】:

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

    <View
            android:layout_width="@{paramsMessage.width, default=@dimen/default_width}"
            android:layout_height="@{paramsMessage.height, default=@dimen/default_height}"
    ... />
    

    【讨论】:

      【解决方案2】:

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

      我在视图中将 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
      }
      

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

      class SomeController(val someFragment: SomeFragment){
          fun getDeviceWidthDP(): Float{
              val width = someFragment.context.getDeviceDimensions().first
              return width
          }
      }
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

          • 不正确,数据和Binding适配器之间没有连接