Подтвердить что ты не робот

Метод инфляции для моей привязки не найден (с использованием Android, привязка данных).

Я использую привязку данных для привязки макетов в своем приложении для Android.

Я установил свой макет (my_custom.xml) и создал класс привязки (MyCustomBinding), но Android Studio, похоже, сразу не находит метод .inflate(...) класса Binding, отмечая его как ошибка (красный текст!).

Код кажется правильным, потому что он компилирует и строит просто в APK.

Как я могу правильно настроить Android Studio?

Пример кода:

Это мой пользовательский код просмотра:

    public class MyCustomView extends FrameLayout {
    public MyCustomView(Context context) {
        this(context, null, 0);
    }
    public MyCustomView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        MyCustomBinding binding = MyCustomBinding.inflate(inflater, this, true);
        binding.aButton.setText("Whatever");
    }
}
Макет

определяется как:

    <?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
    </data>
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <TextView
            android:id="@+id/a_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Click me!"
            android:padding="10dp"
            android:background="#000"
            android:textColor="#fff"
            android:layout_gravity="center"
            />
    </FrameLayout>
</layout>

И вот проблема: (выделено красным)

введите описание изображения здесь

4b9b3361

Ответ 1

Что-то не заканчивается в Android Studio, потому что вы фактически не реализовали привязку данных. Когда вы добавите переменную в свой макет data, метод inflate будет найден, как вы ожидаете. Тем не менее, вы действительно не получаете преимущества привязки данных, устанавливая значение текстового поля непосредственно через привязку. Вместо этого вы должны установить модель просмотра в своей привязке, а затем позволить привязке обновлять представления соответственно. Например:

создать модель просмотра:

public class MyViewModel {
    public final ObservableField<String> name;
    public MyViewModel(String name) {
        this.name = new ObservableField<>(name);
    }
}

и использовать его в своем макете

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="model" type="com.victoriaschocolates.conceirge.MyViewModel" />
    </data>
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{model.name}"
            android:padding="10dp"
            android:background="#000"
            android:textColor="#fff"
            android:layout_gravity="center"
            />
    </FrameLayout>
</layout>

(обратите внимание на variable, объявленный в элементе data, и как он ссылается в атрибуте TextView text)

затем привяжите их в своем пользовательском представлении:

public class MyCustomView extends FrameLayout {

    public MyCustomView(Context context) {
        this(context, null, 0);
    }

    public MyCustomView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        MyCustomBinding binding = MyCustomBinding.inflate(inflater, this, true);
        MyViewModel model = new MyViewModel("Whatever");
        binding.setModel(model);
    }
}

Конечно, было бы лучше, если бы данные передавались через сеттер в пользовательском классе представления или даже передавались из представления контейнера (см. http://developer.android.com/tools/data-binding/guide.html#includes)

Ответ 2

Вы можете попробовать установить собственное имя класса в свой макет привязки и ссылаться на него в своем пользовательском представлении, чтобы выяснить, какой формат вы используете:

<layout>
    <data class="MyCustomBinding">
    </data>
</layout>

Если это не сработает, используйте DataBindingUtil вместо MyCustomBinding, который возвращает базовый класс DataBinding и имеет метод inflate():

MyCustomBinding binding = DataBindingUtil.inflate(inflater, this, true);

Из docs:

Иногда привязка не может быть известна заранее. В таких случаях привязка может быть создана с использованием класса DataBindingUtil:

ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);

Ответ 3

Вам не нужен этот тип материалов, DataBinding включает класс DataBindingUtils, который мы идем.

public MyCustomView(Context context, AttributeSet attrs, int defStyle){
    super(context, attrs, defStyle);
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    MyCustomBinding binding = DataBindingUtil.inflate(inflater, this, true);
    binding.aButton.setText("Whatever");
}

Ответ 4

Это обновленный ответ, основанный на последней привязке данных и androidx, я пришел сюда по этому вопросу, чтобы решить свою собственную проблему, после просмотра приведенных выше ответов я разработал собственный фрагмент рабочего кода. надеюсь, это поможет

    public class CustomActionBar1 extends RelativeLayout {

    public MutableLiveData<String> title = new MutableLiveData<>("Sample text");
    CustomActionBar1Binding binding;

    public CustomActionBar1(Context context) {
        super(context);
        init(context, this);
    }

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

    public CustomActionBar1(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, this);
    }

    public CustomActionBar1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, this);
    }

    private void init(Context context, ViewGroup viewGroup) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        binding = DataBindingUtil.inflate(inflater, R.layout.custom_action_bar_1, viewGroup, true);
    }

    // helper to change title
    public void changeTitle(String title) {
        if (title != null)
            this.title.setValue(title);
    }

    public void setTitleVisibility(Boolean visibile){
        binding.titleText.setVisibility(visibile ? View.VISIBLE : View.INVISIBLE);
    }

}

Xml

<?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="customActionBar1"
            type="com.actionBar.CustomActionBar1" />
    </data>

    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:background="@color/yellow"
        android:layout_height="@dimen/action_bar_height"
        android:id="@+id/main_header_relative">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="@{customActionBar1.title}"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:id="@+id/titleText"
        android:visibility="visible"
         android:textColor="@color/black" />


    </RelativeLayout>
</layout>