Получить значение из фрагмента диалогового окна нижнего листа

Я начинаю bottomSheetDialogFragment из фрагмента A. Я хочу выбрать дату из этого bottomSheetDialogFragment, а затем установить ее во фрагменте A.

Дата выбора уже сделана, я просто хочу получить ее во фрагменте А, чтобы установить ее в некоторых полях.

Как я могу получить значение? Любые предложения, как это сделать?


person Abdulrahman    schedule 12.04.2018    source источник
comment
Поделитесь своим кодом   -  person Shubham Srivastava    schedule 12.04.2018
comment
Создайте один интерфейс. Реализуйте этот интерфейс во фрагменте A, затем передайте ссылку на этот интерфейс в BottomSheetDialog, когда вы меняете дату, в этом методе вызовите этот метод интерфейса и передайте свою дату в параметре метода. Теперь у вас есть дата во фрагменте А, используйте ее.   -  person Däñish Shärmà    schedule 12.04.2018
comment
Можешь написать пример?   -  person Abdulrahman    schedule 12.04.2018


Ответы (8)


Создайте класс интерфейса, подобный этому

public interface CustomInterface {

    public void callbackMethod(String date);
}

Реализуйте этот интерфейс в своем Activity или Fragment. и сделать объект этого интерфейса.

private CustomInterface callback;

Инициализируйте его в onCreate или onCreateView

callback=this;

Теперь передайте этот обратный вызов в свой конструктор BottomSheetDialogFragment, когда вы его вызываете.

yourBottomSheetObject = new YourBottomSheet(callback);
yourBottomSheetObject.show(getSupportFragmentManager()," string");

Теперь в конструкторе вашего BottomSheetFragment

частный обратный вызов CustomInterface;

public SelectStartTimeSheet(CustomInterface callback){

this.callback=callback;

}

И, наконец, используйте этот объект обратного вызова, чтобы установить дату

callback.callbackMethod("your date");

и вы получите эту дату в своем фрагменте или функции «Ваша активность в callbackMethod».

person AbhayBohra    schedule 12.04.2018
comment
это не работает для меня. когда я создаю конструктор с аргументом в нижней части листа, он выдает предупреждение о том, что избегайте конструкторов не по умолчанию во фрагментах ... любой обходной путь? Благодарность - person jackycflau; 12.06.2018
comment
Просто поместите эту строку @SuppressLint(ValidFragment) над именем вашего класса - person AbhayBohra; 12.06.2018
comment
Не подавляйте, вы можете сделать: fragment.setCallbackListener(listener). Но это все еще не предпочтительный способ, если вы звоните из фрагмента или действия. вы можете использовать getTargetFragment(), например, в случае фрагмента - person Andrea Aranguren; 16.07.2018
comment
@AndreaAranguren дал лучшее решение, используя getTargetFragment. Это должен быть выбранный ответ - person Avi; 27.03.2019

переопределение конструктора фрагмента является плохой практикой, поскольку в документе говорится:

Каждый фрагмент должен иметь * пустой конструктор, чтобы его можно было создать при восстановлении * состояния активности.

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

рекомендуется использовать viewModel и livedata.

person hglf    schedule 29.05.2019

Компонент архитектуры навигации Android

eg:

Предположим, вы открываете фрагмент B из фрагмента A с помощью navController.

и вам нужны данные из фрагмента B во фрагмент A.

class B :BottomSheetDialogFragment() {

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.your_layout, container, false)

        root.sampleButton.setOnClickListener {
            val navController = findNavController()
            navController.previousBackStackEntry?.savedStateHandle?.set("your_key", "your_value")
            dismiss()

        }
}

и в вашем фрагменте A:

findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("your_key")
                ?.observe(viewLifecycleOwner) {
    
                    if (it == "your_value") {
                        //your code
    
                    }
    
                }
person Yogesh Nikam Patil    schedule 10.03.2021

вы можете использовать сделать, как показано ниже:

Выберите код фрагмента учетной записи


class SelectAccountFragment(val clickListener: OnOptionCLickListener) : BottomSheetDialogFragment() {


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.bottom_fragment_accounts, container, false)
    }



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

        val list = DataProcessorApp(context).allUsers

        val rvAccounts = view.findViewById<RecyclerView>(R.id.rvAccounts)

        rvAccounts.layoutManager = LinearLayoutManager(context)
        rvAccounts.adapter = AccountsAdapter(context, list)

        Log.e(tag,"Accounts "+list.size);

        tvAccountAdd.setOnClickListener {
            val intent = Intent(context,LoginActivity::class.java)
            startActivity(intent)
        }

        tvManageAccounts.setOnClickListener {
            Log.e(tag,"Manage Click")
            clickListener.onManageClick()
        }
    }


    interface OnOptionCLickListener{
        fun onManageClick()
    }

}


Теперь покажите и получите обратный вызов в другой фрагмент/активность, как показано ниже.

 SelectAccountFragment accountFragment = new SelectAccountFragment(() -> {

          //get fragment by tag and dismiss it

          BottomSheetDialogFragment fragment = (BottomSheetDialogFragment) getChildFragmentManager().findFragmentByTag(SelectAccountFragment.class.getSimpleName();
          if (fragment!=null){
               fragment.dismiss();
          }

});

accountFragment.show(getChildFragmentManager(),SelectAccountFragment.class.getSimpleName());
person imran khan    schedule 09.07.2019

Если вы используете BottomSheetDialogFragment , так как это фрагмент, вы должны создать свой интерфейс и привязать его к методу жизненного цикла onAttach фрагмента , выполнив соответствующее приведение ссылки активности на ваш тип слушателя/обратного вызова.

Внедрите этот интерфейс в свою деятельность и отправьте изменение, когда кто-то щелкнет элемент внутреннего recyclerview фрагмента, например

Это хорошо известный шаблон, который лучше объясняется на странице здесь

Один большой совет — переосмыслить архитектуру вашего приложения, так как лучший подход — всегда передавать примитивные/простые/крошечные данные между компонентами Android через Bundle, и ваши компоненты смогут позже получить требуемое состояние со своими зависимостями.

Например, вы никогда не должны передавать большие объекты, такие как растровые изображения, классы данных, DTO или ссылки на представления.

  • во-первых, в отношении Parcel происходит некоторый процесс сериализации, который влияет на отзывчивость приложения.
  • во-вторых, это может привести к ошибке типа TransactionTooLarge.

Надеюсь, это поможет!

person william gouvea    schedule 02.10.2019

Вы также можете использовать LocalBroadcastManager. И, как сказал hglf, лучше оставить пустой конструктор для вашего фрагмента и использовать вместо этого newInstance(Type value) для создания экземпляра вашего фрагмента, если вы все еще хотите использовать интерфейс callBack.

person Abdelkader    schedule 01.06.2019

Вы можете использовать преимущества библиотеки Navigation:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val navController = findNavController();
    // After a configuration change or process death, the currentBackStackEntry
    // points to the dialog destination, so you must use getBackStackEntry()
    // with the specific ID of your destination to ensure we always
    // get the right NavBackStackEntry
    val navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment)

    // Create our observer and add it to the NavBackStackEntry's lifecycle
    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME
            && navBackStackEntry.savedStateHandle.contains("key")) {
            val result = navBackStackEntry.savedStateHandle.get<String>("key");
            // Do something with the result
        }
    }
    navBackStackEntry.lifecycle.addObserver(observer)

    // As addObserver() does not automatically remove the observer, we
    // call removeObserver() manually when the view lifecycle is destroyed
    viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            navBackStackEntry.lifecycle.removeObserver(observer)
        }
    })
}

Для получения дополнительной информации прочитайте документ.

person Kaaveh Mohamedi    schedule 15.02.2021

Принятый ответ неверен.

Что вы можете сделать, так это просто пользовательский Fragment A childFragmentManager при вызове show().

как это:

val childFragmentManager = fragmentA.childFragmentManager
bottomSheetDialogFragment.show(childFragmentManager, "dialog") 
person Alécio Carvalho    schedule 01.10.2020