#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 внутри фрагмента