web-dev-qa-db-ja.com

Androidデータバインディングが<merge>属性で機能しない

カスタムビューでデータバインディングを使用しようとしています(可能な使用法はGeorge Mountが示した here です)。

<merge>タグなしで複合ビューを構築することは想像できません。ただし、この状況ではデータバインディングが失敗します。

MyCompoundViewクラス:

public class MyCompoundView extends RelativeLayout {

MyCompoundViewBinding binding;

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

private void init(Context context){
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    binding = MyCompoundViewBinding.inflate(inflater, this, true);
}

my_compound_view.xml:by app:isGone="@{!data.isViewVisible}"複合ビュー全体の可視性を制御したい

<?xml version="1.0" encoding="utf-8"?>

<layout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    >

    <data>
        <variable name="data" type="com.example.MyViewModel"/>
    </data>

    <merge
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        app:isGone="@{!data.isViewVisible}">

        <ImageView
            Android:id="@+id/image_image"
            Android:layout_width="60dp"
            Android:layout_height="60dp"
            app:imageUrl="@{data.imagePhotoUrl}"/>

         <!-- tons of other views-->

    </merge>

</layout>

コンパイラエラー:

Error:(13) No resource identifier found for attribute 'isGone' in package 'com.example'
Error:(17, 21) No resource type specified (at 'isGone' with value '@{!data.isViewVisible}').

すべての@BindingAdapterメソッドが必要です。今私はFrameLayoutからビューを継承し、<RelativeLayout>の代わりに<merge>を使用します-そしてそれは動作します。しかし、私は追加のネストされたレイアウトを持っています。

質問:merge attrsは無視されます。それを回避する方法はありますか?

Android Studio 1.5.1安定

Gradleプラグインcom.Android.tools.build:gradle:1.5.0

21
Dmitry Gryazin

インフレーション後はマージオブジェクトがないため、マージタグで値を割り当てるものはありません。マージで機能するバインディングタグは考えられません。

タグをルート要素に割り当て、BindingAdapterを使用して必要な操作を実行できます。

<layout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    >

    <data>
        <variable name="data" type="com.example.MyViewModel"/>
    </data>

    <merge
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content">
        <ImageView
            app:isGone="@{!data.isViewVisible}"
            Android:id="@+id/image_image"
            Android:layout_width="60dp"
            Android:layout_height="60dp"
            app:imageUrl="@{data.imagePhotoUrl}"/>
         <!-- tons of other views-->
    </merge>
</layout>

Bindingクラス自体で何かを実行したい場合は、DataBindingUtilを使用してビューからオブジェクトを検索できます。

@BindingAdapter("isGone")
public static void setGone(View view, boolean isGone) {
    ViewDataBinding binding = DataBindingUtil.findBinding(view);
    //... do what you want with the binding.
}
15
George Mount

実際には<merge>タグ内<include>とデータバインディングを行います。

例:

incl_button.xml

<layout>
    <merge xmlns:Android="http://schemas.Android.com/apk/res/Android">

        <Button Android:id="btn"
             Android:layout_width="wrap_content"
             Android:layout_height="wrap_content"
             Android:text="Click"
         />

    </merge>
</layout>

fragment_example.xml

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android">

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

        <include
            layout="@layout/incl_button"
            Android:id="@+id/layout_btn" />

    </LinearLayout>
</layout>

ExampleFragment.kt

binding.layoutBtn.btn.setOnClickListener{
   //...
}
0
user158