【问题标题】:Pass data from Fragment to Activity with FAB使用 FAB 将数据从 Fragment 传递到 Activity
【发布时间】:2021-01-02 16:50:46
【问题描述】:

我有一个打开的活动,带有一个 FAB 按钮,里面有一个片段。主要活动有一个带有书籍清单的recyclerview。当我点击 fab 时,我打开了片段,fab 按钮变成了“关闭片段按钮”,另一个 fab 出现在附近以保存新元素。事实上片段有一些文本视图和图像视图由用户填写。我的问题是:如何使用保存 fab 按钮将片段上的新元素对象传递给活动?

主要活动:

class MainActivity : AppCompatActivity() {

private var recyclerView: RecyclerView? = null
private var classArray: ArrayList<ClassItem>? = null
private var gridLayoutManager: GridLayoutManager? = null
private var classAdapter: ClassAdapter? = null
private var isRotate = true

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(findViewById(R.id.toolbar))


    val saveFab = findViewById<FloatingActionButton>(R.id.saveFab)

    initFab(saveFab)

    saveFab.setOnClickListener{

        //I think that I need to do something here

        classAdapter?.notifyDataSetChanged()
        //Close the fragment
        onBackPressed()
    }

    findViewById<FloatingActionButton>(R.id.fabButton).setOnClickListener {
        saveFab.visibility = if(saveFab.visibility == View.VISIBLE) {
            View.GONE
        } else {
            View.VISIBLE
        }
/*Animation fab code
  ....
*/

        if(isRotate){
            showInFab(saveFab)
           
            supportFragmentManager.open {
                // Pass center as the end position of the circular reveal
                add(R.id.container, AddClassFragment.newInstance(positions)).addToBackStack(null)
            }
        } else {
            showOutFab(saveFab)
            recyclerView?.visibility = View.VISIBLE
            findViewById<ImageView>(R.id.imageView2).visibility = View.VISIBLE

            with(supportFragmentManager.findFragmentById(R.id.container)) {
                // Check if the current fragment implements the [ExitWithAnimation] interface or not
                // Also check if the [ExitWithAnimation.isToBeExitedWithAnimation] is `true` or not
                if ((this as? ExitWithAnimation)?.isToBeExitedWithAnimation() == true) {
                    if (this.posX == null || this.posY == null) {
                        super.onBackPressed()
                    } else {
                        this.view?.exitCircularReveal(this.posX!!, this.posY!!) {
                            super.onBackPressed()
                        } ?: super.onBackPressed()
                    }
                } else {
                    super.onBackPressed()
                }
            }
        }


        isRotate = rotateFab(it, isRotate)
    }
    recyclerView = findViewById(R.id.ClassesRecyclerView)

    gridLayoutManager = GridLayoutManager(
        applicationContext,
        1,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    recyclerView?.layoutManager = gridLayoutManager
    recyclerView?.setHasFixedSize(true)
    val snapHelper = LinearSnapHelper()
    snapHelper.attachToRecyclerView(recyclerView)

    classArray = setClasses()
    classAdapter = ClassAdapter(applicationContext, classArray!!)
    recyclerView?.adapter = classAdapter
}


override fun onBackPressed() {
    //Close fragment or exit app code
}



private fun setClasses(): ArrayList<ClassItem> {
       //init the classArray code
    }
 }

这是片段:

class AddClassFragment: Fragment(), ExitWithAnimation {

override var posX: Int? = null
override var posY: Int? = null
override fun isToBeExitedWithAnimation(): Boolean = true
private var colorAdapter: ChooseColorAdapter? = null
private var recyclerView: RecyclerView? = null
private var colorArray: ArrayList<Int>? = null
private var gridLayoutManager: GridLayoutManager? = null
private var title: TextView? = null
private var colorBook: Int? = null

companion object {
    @JvmStatic
    fun newInstance(exit: IntArray? = null): AddClassFragment = AddClassFragment().apply {
        if (exit != null && exit.size == 2) {
            posX = exit[0]
            posY = exit[1]
        }
    }
}

private fun setColor(): ArrayList<Int> {
    return arrayListOf(Color.BLACK, Color.CYAN, Color.YELLOW, Color.GREEN, Color.RED, Color.GRAY, Color.MAGENTA, Color.WHITE)
}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {

    val view: View = inflater.inflate(R.layout.fragment_add_class, container, false)

    title = view.findViewById(R.id.title_text_view)
    recyclerView = view.findViewById(R.id.colorRecyclerView)
    
    //Grid layout to choose the color of the book
    gridLayoutManager = GridLayoutManager(
        view.context,
        1,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    recyclerView?.layoutManager = gridLayoutManager
    recyclerView?.setHasFixedSize(true)

    colorArray = setColor()
    colorAdapter = ChooseColorAdapter(view.context, colorArray!!) {
        val bookCover: ImageView = view.findViewById(R.id.add_class_cover_book)

        bookCover.setColorFilter(it, PorterDuff.Mode.MULTIPLY)

        colorBook = it
    }
    recyclerView?.adapter = colorAdapter

    return view
}

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

}

【问题讨论】:

    标签: android kotlin android-fragments android-activity floating-action-button


    【解决方案1】:

    我认为您可以将saveFab 按钮移动到AddClassFragment 并添加从AddClassFragmentMainActivity 的回调,例如:

    class MainActivity : AppCompatActivity(), AddClassFragment.Listener {
    
        ........
        override fun saveButtonPressed( data : SomeData){
            //Do something with data
            println(" Data -> $data")
        }
    
        override fun popBackStack(){
            classAdapter?.notifyDataSetChanged()
            //Close the fragment
            onBackPressed()
        }
    }
    
    class AddClassFragment: Fragment(), ExitWithAnimation {
        interface Listener{
            fun saveButtonPressed(data: SomeData)
            fun popBackStack()
        }
    
        private val listener: Listener? = null
    
        override fun onAttach(context: Context) {
            super.onAttach(context)
            if (context is Listener) {
                listener = context
            }
        }
    
        ........
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            view.startCircularReveal(false)
        
            ...
            saveFab.setOnClickListener{
                val data = getDataFromSomeSource()
                listener?.saveButtonPressed(data = data)
                listener?.popBackStack() 
            }
            
        }     
    }
    

    更新

    想法:您可以在片段中创建一个公共方法,然后使用supportFragmentManager.findFragmentById()从活动中调用它

    类 MainActivity : AppCompatActivity(), AddClassFragment.Listener {

        ........
    
        override fun onCreate(savedInstanceState: Bundle?) {
            ........
            saveFab.setOnClickListener{
                val fragment = supportFragmentManager.findFragmentById(R.id.CONTAINER_ID)
         
                if(fragment != null && fragment is AddClassFragment){
                    val data = fragment. getDataFromForm()
                    // do Something with data
                    println(" Data -> $data")
                }
            }
        }
    }
    
    class AddClassFragment: Fragment(), ExitWithAnimation {
    
    
        ........
    
        // this methods return the data after the user filled the 
        // necessary input
        fun getDataFromForm(): SomeData = getDataFromSomeSource()    
    }
    

    【讨论】:

    • 感谢您的回复。问题是我在 Fragment 中没有引用 saveFab 所以在 onViewCreated 我有一个错误。
    • 是的,您应该将 savefabbutton 从活动移动到片段
    • 问题是我不能,因为我需要第一个工厂的参考才能正确显示动画
    • 我明白了。我添加了另一种方法
    • 是的,我已经像你写的那样解决了。我只使用supportFragmentManager.findFragmentByTag()。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2013-07-26
    相关资源
    最近更新 更多