android数据绑定与自定义视图

Dav*_*ave 45 data-binding android custom-view

所述的Android数据绑定导向讨论了一个活动或片段内结合的值,但是有执行数据与自定义视图结合的方法吗?

我想做的事情如下:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mypath.MyCustomView
        android:id="@+id/my_view"
        android:layout_width="match_parent"
        android:layout_height="40dp"/>

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

my_custom_view.xml:

<layout>

<data>
    <variable
        name="myViewModel"
        type="com.mypath.MyViewModelObject" />
</data>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{myViewModel.myText}" />

</LinearLayout>

</layout>
Run Code Online (Sandbox Code Playgroud)

虽然看起来可以通过在自定义视图上设置自定义属性来实现这一点,但如果要绑定很多值,这很快就会变得很麻烦.

有没有一个好方法来完成我想要做的事情?

Geo*_*unt 57

在自定义视图中,按照通常的方式对布局进行膨胀,并为要设置的属性提供一个setter:

private MyCustomViewBinding mBinding;
public MyCustomView(...) {
    ...
    LayoutInflater inflater = (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mBinding = MyCustomViewBinding.inflate(inflater);
}

public void setMyViewModel(MyViewModelObject obj) {
    mBinding.setMyViewModel(obj);
}
Run Code Online (Sandbox Code Playgroud)

然后在布局中使用它:

<layout xmlns...>
    <data>
        <variable
            name="myViewModel"
            type="com.mypath.MyViewModelObject" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.mypath.MyCustomView
            android:id="@+id/my_view"
            app:myViewModel="@{myViewModel}"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

    </LinearLayout>
</layout>
Run Code Online (Sandbox Code Playgroud)

在上面,为app:myViewModel创建了一个自动绑定属性,因为有一个名为setMyViewModel的setter.

  • 另外,记得定义并附加到root:`inflate(inflater,this,true)`.在我的情况下,我需要它可以看到自定义视图. (5认同)
  • 使用`LayoutInflater.from(context)`,它更好 - 更短,你不必进行类型转换. (4认同)
  • MyCustomViewBinding 是通过注释处理器生成的,作为数据绑定框架的一部分。xml 文件(Dave 使用了 MyCustomView.xml,但他实际上是指 my_custom_view.xml,因为资源文件的大小写应该全部小写)导致 MyCustomViewBinding(驼峰式大小写,后缀为 Binding)的默认 Binding 类名称。您还可以自定义 Binding 类名称:http://developer.android.com/tools/data-binding/guide.html#custom_binding_class_names (3认同)
  • http://stackoverflow.com/a/36068337/1369016(也由 George Mount 发布)中描述的解决方案对我有用。 (2认同)

and*_*guy 8

首先,如果此自定义视图已经<include>在另一个布局中(例如活动等),则不要执行此操作。您将仅获得有关标记为意外值的异常。数据绑定已经在其上运行了绑定,因此已设置好。

您是否尝试使用onFinishInflate运行绑定?(Kotlin示例)

override fun onFinishInflate() {
    super.onFinishInflate()
    this.dataBinding = MyCustomBinding.bind(this)
}
Run Code Online (Sandbox Code Playgroud)

请记住,如果您在视图中使用绑定,则将无法以编程方式创建该绑定,至少,即使可以,也很难解决这两个问题。


小智 8

数据绑定工作即使合并只有父必须是“这个”并附加到父真。

binding = DataBindingUtil.inflate(inflater, R.layout.view_toolbar, this, true)
Run Code Online (Sandbox Code Playgroud)


小智 6

今天,我想在我的自定义视图类上使用数据绑定。但我不知道如何创建到我的类的数据绑定。所以我在 StackOverflow 上搜索答案。首先我尝试回答:

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
BottomBarItemCustomViewBinding binding = BottomBarItemCustomViewBinding.inflate(inflater);
Run Code Online (Sandbox Code Playgroud)

但是,我发现这不适用于我的代码

所以我改变了另一种方法:

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
BottomBarItemCustomViewBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_bar_item_custom_view, this, true);
Run Code Online (Sandbox Code Playgroud)

它对我有用。

完整的代码是:bottom_bar_item_custom_view.xml

<data>

    <variable
        name="contentText"
        type="String" />

    <variable
        name="iconResource"
        type="int" />

</data>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center">

    <ImageView
        android:id="@+id/bottomBarItemIconIv"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginTop="2dp"
        android:src="@{iconResource}"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/bottomBarItemContentTv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="@{contentText}"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/bottomBarItemIconIv" />


</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

BottomBarItemCustomView.java

public class BottomBarItemCustomView extends ConstraintLayout {

public BottomBarItemCustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    //use dataBinding on custom view.
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    BottomBarItemCustomViewBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_bar_item_custom_view, this, true);

    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BottomBarItemCustomView);
    int iconResourceId = typedArray.getResourceId(R.styleable.BottomBarItemCustomView_bottomBarIconResource, R.drawable.my_account_icon);
    binding.setIconResource(iconResourceId);

    String contentString = typedArray.getString(R.styleable.BottomBarItemCustomView_bottomBarContentText);
    if (contentString != null) {
        binding.setContentText(contentString);
    }

    typedArray.recycle();
}
Run Code Online (Sandbox Code Playgroud)

希望对你有用!


Upv*_*ote 5

按照乔治提出的解决方案,android studio中的图形编辑器不再能够呈现自定义视图。原因是,在以下代码中实际上没有视图被夸大:

public MyCustomView(...) {
    ...
    LayoutInflater inflater = (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mBinding = MyCustomViewBinding.inflate(inflater);
}
Run Code Online (Sandbox Code Playgroud)

我认为绑定处理了通货膨胀,但是图形编辑器不喜欢它。

在我的特定用例中,我想绑定一个字段而不是整个视图模型。我想出了(kotlin传入):

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

    val layout: ConstraintLayout = LayoutInflater.from(context).inflate(R.layout.like_button, this, true) as ConstraintLayout

    var numberOfLikes: Int = 0
      set(value) {
          field = value
          layout.number_of_likes_tv.text = numberOfLikes.toString()
      }
}
Run Code Online (Sandbox Code Playgroud)

“喜欢”按钮由图像和文本视图组成。文本视图包含喜欢的数量,我想通过数据绑定设置喜欢的数量。

通过将numberOfLikes的setter用作以下xml中的属性,数据绑定将自动建立关联:

<views.LikeButton
  android:id="@+id/like_btn"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:numberOfLikes="@{story.numberOfLikes}" />
Run Code Online (Sandbox Code Playgroud)

进一步阅读:https : //medium.com/google-developers/android-data-binding-custom-setters-55a25a7aea47