Как получить доступ к представлениям из макета, содержащего тег слияния, включенный в другой макет? - PullRequest
3 голосов
/ 15 января 2020

Я использую Android Studio 3.6-RC1 и инструменты сборки версии 3.6.0-rc01 и обнаружил проблему с функцией ViewBinding:

У меня есть файл activity_test. xml со следующей разметкой:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/view_merged"
        layout="@layout/merge_view" />
</LinearLayout>

И merge_view. xml со следующей разметкой:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Merge view" />
</merge>

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

class TestActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityTestBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.viewMerged.label.text = "New text"

    }
}

Проблема в том, что я пытаюсь получить доступ к TextView из объединенного макета приложение выдает исключение с сообщением java.lang.NullPointerException: Missing required view with ID: viewMerged.

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

public final class ActivityTestBinding implements ViewBinding {
  @NonNull
  private final LinearLayout rootView;

  @NonNull
  public final MergeViewBinding viewMerged;

  private ActivityTestBinding(@NonNull LinearLayout rootView,
      @NonNull MergeViewBinding viewMerged) {
    this.rootView = rootView;
    this.viewMerged = viewMerged;
  }

  @Override
  @NonNull
  public LinearLayout getRoot() {
    return rootView;
  }

  @NonNull
  public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater) {
    return inflate(inflater, null, false);
  }

  @NonNull
  public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup parent, boolean attachToParent) {
    View root = inflater.inflate(R.layout.activity_test, parent, false);
    if (attachToParent) {
      parent.addView(root);
    }
    return bind(root);
  }

  @NonNull
  public static ActivityTestBinding bind(@NonNull View rootView) {
    // The body of this method is generated in a way you would not otherwise write.
    // This is done to optimize the compiled bytecode for size and performance.
    String missingId;
    missingId: {
      View viewMerged = rootView.findViewById(R.id.view_merged);
      if (viewMerged == null) {
        missingId = "viewMerged";
        break missingId;
      }
      MergeViewBinding viewMergedBinding = MergeViewBinding.bind(viewMerged);
      return new ActivityTestBinding((LinearLayout) rootView, viewMergedBinding);
    }
    throw new NullPointerException("Missing required view with ID: ".concat(missingId));
  }
}

Я что-то пропустил или нет доступа виды из включенных макетов с тегами или они еще не доставлены в Android Studio 3.6-RC1?

Ответы [ 2 ]

5 голосов
/ 17 февраля 2020

Я написал статью об использовании ViewBinding с тегом <merge>, который вы можете найти здесь

В основном вам нужно

  • Дон не присваивайте <include> метки любому идентификатору.
  • Вызовите bind() метод сгенерированной привязки макета слияния, передавая представление root макета, в который вы включили макет.
  • Доступ к вашему представление из объекта привязки слиянием

Например, у вас есть merge_view.xml, поэтому у вас будет сгенерирован класс MergeViewBinding, и вы получите доступ к представлению из этого макета.

class TestActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityTestBinding.inflate(layoutInflater)
        val mergeBinding = MergeViewBinding.bind(binding.root)
        setContentView(binding.root)
        mergeBinding.label.text = "New text"
    }
}
0 голосов
/ 15 января 2020

Это может помочь тебе. вы можете использовать макет слияния внутри include, а затем получить доступ к нему ссылка

...