Вопрос по передаче данных между 2мя xml layouts
У меня есть один XML, который я как шаблон хотел бы многократно использовать в другом основном XML. Насколько я понял, это можно сделать через include, и это работает.
Но возникает необходимость менять значение android:text у TextView, который находится внутри 1го шаблонного XML, для каждого нового блока внутри основного XML. Я пересмотрел уже кучу примеров в интернете и делаю через data binding так:
Шаблон, который многократно используется в основном 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="settingName"
type="java.lang.String" />
</data>
<LinearLayout
android:layout_marginHorizontal="24dp"
android:layout_marginVertical="24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{settingName}"
app:drawableRightCompat="@drawable/ic_baseline_arrow_drop_down_circle_24" />
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>
Основной 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"
xmlns:tools="http://schemas.android.com/tools">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingsFragment">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/profile"
layout="@layout/settingblocklayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:settingName='@{"Profile"}' />
<include
android:id="@+id/sport_kinds"
layout="@layout/settingblocklayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:settingName='@{"Sport kind"}' />
</LinearLayout>
</ScrollView>
</layout>
В Activity у меня код такой:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app);
DataBindingUtil.setContentView(AppActivity.this, R.id.settingsFragment);
}
Причём есть проблема со строкой:
DataBindingUtil.setContentView(AppActivity.this, R.id.settingsFragment);
Без неё приложение запускается, но не работает binding и вместо текстовых строк "Profile" и "Sport" подтягивается пустая строка.
А с DataBindingUtil приложение не запускается и падает с ошибкой:
2021-08-15 21:09:08.045 12287-12287/com.eugvol.unitimer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.eugvol.unitimer, PID: 12287
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.eugvol.unitimer/com.eugvol.unitimer.AppActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x7f08018d type #0x12 is not valid
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7f08018d type #0x12 is not valid
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2406)
at android.content.res.Resources.getLayout(Resources.java:1252)
at android.view.LayoutInflater.inflate(LayoutInflater.java:530)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:303)
at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:284)
at com.eugvol.unitimer.AppActivity.onCreate(AppActivity.java:40)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
Помогите, пожалуйста, разобраться, что не так.
Кстати, если вдруг есть ещё какой-либо способ кроме include, чтобы использовать один xml несколько раз внутри другого с изменением некоторых параметров первого xml (например, android:text у textview), то поделитесь, пожалуйста.
Спасибо!
Ответы (1 шт):
Для тех, кто столкнётся с таким же вопросом, добавлю ещё маленький нюанс, который тоже мне пришлось долго самому искать.
Если байндинг нужно сделать на Activity, то в onCreate нужно вставить такую строку, на пример:
DataBindingUtil.setContentView(AppActivity.this, R.layout.activity_app);
А если нужно сделать байндинг на фрагменте (как было в моём случае), то в onCreateView нужно вставить такую:
View view = DataBindingUtil.inflate(inflater, R.layout.fragment_settings, container, false).getRoot(); ну, и конечно, потом return view; в этом методе.
Только не перепутайте R.id и R.layout, как я выше))