簡體   English   中英

從底部工作表對話框片段中獲取值

[英]Get value from Bottom Sheet Dialog Fragment

我從片段 A 開始 bottomSheetDialogFragment。我想從該 bottomSheetDialogFragment 中選擇日期,然后將其設置在片段 A 中。

選擇日期已經完成,我只是想在片段A中獲取它以在某些字段中設置它。

我怎樣才能獲得價值? 任何建議如何做到這一點?

創建一個這樣的接口類

public interface CustomInterface {

    public void callbackMethod(String date);
}

在您的ActivityFragment實現此接口。 並創建此接口的對象。

private CustomInterface callback;

onCreateonCreateView初始化

callback=this;

現在,當您調用它時,在您的BottomSheetDialogFragment構造函數中傳遞此回調。

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

現在在您的BottomSheetFragment 的構造函數中

私有自定義接口回調;

public SelectStartTimeSheet(CustomInterface callback){

this.callback=callback;

}

最后使用這個回調對象來設置你的日期

callback.callbackMethod("your date");

並且您將在您的 Fragment 或您的 Activity 中的callbackMethod函數中收到此日期。

正如文檔所說,覆蓋片段的構造函數是一種不好的做法:

每個片段必須有一個 * 空的構造函數,因此它可以在恢復其活動的狀態時被實例化。

如果您使用另一個將回調作為參數傳遞的構造函數,則當框架恢復片段時,您的應用程序會崩潰

推薦的方法是使用 viewModel 和 livedata。

Android導航架構組件

例如:

假設您使用 navController 從片段 A 打開片段 B。

並且您想要一些從片段 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
    
                    }
    
                }

您可以使用如下方法:

選擇帳戶片段代碼


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());

如果您正在使用 BottomSheetDialogFragment ,因為它是一個片段,您應該創建您的接口並在片段的 onAttach 生命周期方法中綁定到它,對您的偵聽器/回調類型進行適當的活動引用轉換。

例如,在您的 Activity 中實現此接口並在有人單擊 Fragment 內部 recyclerview 的項目時調度更改

這是一個眾所周知的模式,在這里有更好的解釋

一個重要的建議是重新考慮您的應用程序架構,因為最好的方法是始終通過 Bundle 在 Android 組件之間傳遞原始/簡單/微小數據,並且您的組件稍后能夠檢索所需狀態及其依賴項。

例如,你永遠不應該傳遞像位圖、數據類、DTO 或視圖引用這樣的大對象。

  • 首先有一些關於 Parcel 的序列化過程,這會影響應用程序的響應能力
  • 其次,它可能會導致您出現TransactionTooLarge類型的錯誤。

希望有幫助!

您還可以使用LocalBroadcastManager 正如 hglf 所說,如果您仍然想使用接口回調方式,最好為您的片段保留空構造函數並使用 newInstance(Type value) 來實例化您的片段。

您可以使用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)
        }
    })
}

有關更多信息,請閱讀文檔

接受的答案是錯誤的。

您可以做的只是在調用 show() 時使用用戶 Fragment A 的 childFragmentManager。

像這樣:

val childFragmentManager = fragmentA.childFragmentManager
bottomSheetDialogFragment.show(childFragmentManager, "dialog") 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM