Android динамически включает макет с библиотекой привязки данных

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

У меня есть несколько многоразовых композиций, которые должны иметь каждую активность. например панель инструментов, меню, плавающая кнопка действия.

Я хочу создать общую активность, которая будет реализовывать все эти повторно используемые функции, а затем каждый класс активности будет унаследован от этой общей активности. У меня также есть класс GenericViewModel, и все остальные ViewModel унаследованы от этого универсального класса.

Но у меня проблема с оформлением. Я хочу создать общий файл макета и динамически включить в него подмакет. например

    <?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="data"
            type="com.mypackage.genericViewModel" />
    </data>

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

        <include
            bind:data="@{data}"
            layout="@layout/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <include
            layout="@{Here i want to have dynamic variable}"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout></layout>

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


person Sandro Gedevanishvili    schedule 04.04.2016    source источник


Ответы (1)


Вот мое решение, надеюсь, оно вам поможет, я не думаю, что это хороший способ. Если вы найдете лучший способ, пожалуйста, скажите мне. Спасибо!

Хотя библиотека привязки данных не позволяет динамически включать макет, мы можем использовать разные ViewModel для разных макетов. Я использовал LinearLayout в качестве контейнера для размещения динамического макета, а затем переопределил метод Activity setContentView, чтобы добавить представление в мой контейнер (LinearLayout).

Общая активность

    protected GenericViewBinding mBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);           
        mBinding = DataBindingUtil.setContentView(this, R.layout.generic_view);        
}

    @Override
    public void setContentView(View view) {
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mBinding.container.addView(view,lp);
}

макет generic_view

    <data>
        <variable
            name="genericViewModel"
            type=".viewModel.GenericViewModel"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white">
        <!--a custom view,some generic layout -->
        <.view.base.BaseTitleView 
            android:id="@+id/base_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <LinearLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/base_title"
            android:orientation="vertical">
        </LinearLayout>
    </RelativeLayout>

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

Конкретная активность

//different layout use different ViewModel here,generic logic&layout is in GenericActivity&generic_view layout.
private ActivityConcreteBinding mActivityConcreteBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mActivityConcreteBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.activity_concrete,null,false);
    setContentView(mActivityConcreteBinding.getRoot());
    ConcreteViewModel concreteViewModel = new ConcreteViewModel(mBinding);//mBinding from GenericActivity, deliver it into ConcreteViewModel to do some generic logic.
    ...
}

Мне больше не нужно копировать общий макет для каждого действия.

person Yelin Wu    schedule 05.04.2016
comment
Спасибо, это было полезно для меня - person Sandro Gedevanishvili; 15.04.2016