Как использовать основную кнопку плавающего действия actvitiy из фрагментов в одном действии?

#android #kotlin #android-fragments #floating-action-button

Вопрос:

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

  • HomeFragment -> добавляет новый элемент
  • AddProblemFragment -> сохраняет элемент (также меняется значок)
  • DetailsFragment -> добавляет элементы в выбранные коллекции (также меняется значок)

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

Чтобы решить проблему с щелчком, я получаю ссылку на fab из activity с

fab = requireActivity().findViewById(R.id.fab) в каждом фрагменте (в onViewCreated).

Итак, проблема в том, что после изменения ориентации выдает java.lang.NullPointerException: requireActivity().findViewById(R.id.fab) must not be null

Есть ли способ избежать получения этой ошибки после изменения ориентации? или какой жизненный цикл следует выбрать для инициализации fab?

Можно ли инициализировать fab в BaseFragment и использовать его, потому что почти в каждом фрагменте есть fab?

Фрагменты кода:

 //Each fragment same approach

private lateinit var fab:FloatingActionButton

override fun onViewCreated(view:View,savedInstanceState:Bundle?){

fab = requireActivity().findViewById(R.id.fab_btn_add)
fab.setImageResource(R.drawable.ic_related_icon)
fab.setOnClickListener {
    //calls method
        }
 

Комментарии:

1. Похоже, вы используете устаревший <fragment> тег в XML-макете вашего действия. Есть ли причина, по которой вы не используете FragmentContainerView , которая не страдает от этой проблемы?

2. Это сработало. Я заменил его на FragmentContainerView. <фрагмент> вызывал эту проблему. Большое спасибо.

Ответ №1:

Сначала вам нужно создать интерфейс для прослушивателя щелчков, например:

 interface FabClickCallback {
    
   void onFabClick()

}
 

и на вашей активности,

Вам нужно создать экземпляр из этого обратного вызова

 private FabClickCallback fabCallback;
 

и вы хотите создать новый метод внутри вашего действия, вызываемый, например:

 public void handleFabClickListener(FabClickCallback callback){
   // TODO Here put callback
   this.fabCallback = callback;
}
 

и вы хотите вызвать этот обратный вызов, когда пользователь нажимает на кнопку Fab следующим образом:

 fab.setOnClickListener ( view -> {
  if (this.fabCallback != null ) {
     this.fabCallback.onFabClick();
   }
});
 

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

  ((YourActivity) requireActivity()).handleFabClickListener(this);
 

и ваш фрагмент должен реализовывать интерфейс FabClickCallback

Комментарии:

1. Я бы не стал предлагать это, поскольку это 1) в основном помещает вас в циклический цикл и 2) устанавливает явную зависимость от родительской активности внутри каждого фрагмента. Чтобы оставаться разделенными и повторно используемыми, фрагменты не должны знать о своей активности владельца. См.: developer.android.com/guide/fragments/communicate

2. Я согласен с вами, человек. но это решение работает как простое решение, и эта работа будет работать, даже если он не используется fragment-ktx , поэтому для оптимизации этого решения он может установить FabCallback = null onStop внутри фрагмента