ViewBinding - как получить привязку для включенных макетов?

11

При работе с ViewBinding я сталкиваюсь с несколькими недокументированными случаями.

Первый: Как получить привязку для включенных частей макета общего вида, чтобы основная привязка видела только элементы в основном макете?

Второе: Как получить привязку для включенных частей макета типа слияния, опять-таки основная привязка видит только элементы в основном макете?

Артур Каспрзак
источник

Ответы:

15

В случае:

  1. Включите в общий макет (не узел слияния), нам нужно назначить идентификатор для включенной части, таким образом, в связывании у нас будет доступ к включенной части
<include
    android:id="@+id/your_id"
    layout="@layout/some_layout" />

Таким образом, в коде вашей деятельности:

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
    setContentView(exampleBinding.root)
    //we will be able to access included layouts view like this
    val includedView: View = exampleBinding.yourId.idOfIncludedView
//[...]
}
  1. Включить с блоком слияния во внешнем макете. Мы не можем добавить ID к нему, потому что блок слияния не является представлением. Допустим, у нас есть такой вечный макет слияния (merge_layout.xm):
<?xml version="1.0" encoding="utf-8"?>
<merge 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"
    tools:showIn="@layout/activity_example">

    <TextView
        android:id="@+id/some_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World" />
</merge>

Чтобы правильно связать такой макет слияния, нам нужно:

В коде вашей активности:

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout
private lateinit var mergeBinding: MergeLayoutBinding  //merge_layout.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
    //we need to bind the root layout with our binder for external layout
    mergeBinding = MergeLayoutBinding.bind(exampleBinding.root)
    setContentView(exampleBinding.root)
    //we will be able to access included in merge layout views like this
    val mergedView: View = mergeBinding.someView
//[...]
}
Артур Каспрзак
источник
1
Это похоже на ошибку. Это должно просто работать .
Мигель
7

Ваш первый вопрос о работе с включенным макетом с помощью ViewBinding может быть решен так легко.

Вот пример файла main_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view_main"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

</LinearLayout>

И MainFragment.java может быть таким

public class MeaningFragment extends Fragment {

    private MainFragmentBinding binding;
    private ToolbarBinding toolbarBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        binding = MainFragmentBinding.inflate(inflater, container, false);
        toolbarBinding = binding.toolbar;

        return binding.getRoot();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        toolbarBinding = null;
        binding = null;
    }
}

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

Эми Раз
источник
1
Очень простой ответ и использует новый синтаксис - все работает для меня в не-фрагментной деятельности с похожим синтаксисом в onCreate(). Спасибо. (Просто немного проблем с использованием для DrawerLayout)
Толстый Монах
0

Другим простым способом будет использование библиотеки привязки данных. Затем оберните ваш XML-макет тегом, чтобы при использовании библиотеки автоматически генерировались классы, необходимые для связывания представлений в макете с вашими объектами данных. Честно говоря, я думаю, что это путь. Следуйте инструкциям здесь

Арун Гурунг
источник