TIL

TIL 38일차

김태준(Android_3기) 2024. 4. 11. 19:43

프래그먼트

액티비티 위에서 동작하는 인터페이스

하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있음

프래그먼트 사용 예제

  1. 프래그먼트 파일 생성
  2. xml 파일 정의
  3. MainActivity에 Fragment 추가하기

 

프래그먼트의 데이터 전달

Activity > Fragment 데이터 전달

  1. 보내는 코드
    binding.run {
                fragment1Btn.setOnClickListener{
                    // [1] Activity -> FirstFragment
                    val dataToSend = "Hello First Fragment! \n From Activity"
                    val fragment = FirstFragment.newInstance(dataToSend)
                    setFragment(fragment)
                }
    
                fragment2Btn.setOnClickListener {
                    // [1] Activity -> SecondFragment
                    val dataToSend = "Hello Second Fragment!\n From Activity"
                    val fragment = SecondFragment.newInstance(dataToSend)
                    setFragment(fragment)
                }​
  2. 받는 코드
private var param1: String? = null

companion object {
        @JvmStatic
        fun newInstance(param1: String) =
            // [1] Activity -> FirstFragment
            FirstFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // [1] Activity -> FirstFragment
        binding.tvFrag1Text.text = param1     
}

Fragment > Fragment 데이터 전달

  1. 보내는 코드
    // [2] Fragment -> Fragment
            binding.btnGofrag2.setOnClickListener{
                val dataToSend = "Hello Fragment2! \n From Fragment1"
                val fragment2 = SecondFragment.newInstance(dataToSend)
                requireActivity().supportFragmentManager.beginTransaction()
                    .replace(R.id.frameLayout, fragment2)
                    .addToBackStack(null)
                    .commit()
            }​
  2. 받는 코드

 

private const val ARG_PARAM1 = "param1"

class SecondFragment : Fragment() {

    private var param1: String? = null

    private var _binding: FragmentSecondBinding? = null
    private val binding get() = _binding!!


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSecondBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // [2] Fragment -> Fragment
        binding.tvFrag2Text.text = param1
    }


    companion object {
        @JvmStatic
        fun newInstance(param1: String) =
            // [1] Activity -> FirstFragment
            SecondFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // Binding 객체 해제
        _binding = null
    }
}

 

 

Fragment > Activity 데이터 전달

  1. 보내는 코드
    private const val ARG_PARAM1 = "param1"
    
    interface FragmentDataListener {
        fun onDataReceived(data: String)
    }
    
    class SecondFragment : Fragment() {
    
        // [3] SecondFragment -> Activity
        private var listener: FragmentDataListener? = null
    
        private var param1: String? = null
    
        private var _binding: FragmentSecondBinding? = null
        private val binding get() = _binding!!
    
    
        override fun onAttach(context: Context) {
            super.onAttach(context)
    
            // [3] SecondFragment -> Activity
            if (context is FragmentDataListener) {
                listener = context
            } else {
                throw RuntimeException("$context must implement FragmentDataListener")
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            arguments?.let {
                param1 = it.getString(ARG_PARAM1)
            }
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            _binding = FragmentSecondBinding.inflate(inflater, container, false)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            // [2] Fragment -> Fragment
            binding.tvFrag2Text.text = param1
    
            // [3] SecondFragment -> Activity
            binding.btnSendActivity.setOnClickListener{
                val dataToSend = "Hello from SecondFragment!"
                listener?.onDataReceived(dataToSend)
            }
        }
    
    
        companion object {
            @JvmStatic
            fun newInstance(param1: String) =
                // [1] Activity -> FirstFragment
                SecondFragment().apply {
                    arguments = Bundle().apply {
                        putString(ARG_PARAM1, param1)
                    }
                }
        }
    
        override fun onDestroyView() {
            super.onDestroyView()
            // Binding 객체 해제
            _binding = null
            listener = null
        }
    }​
  2. 받는 코드
class MainActivity : AppCompatActivity(), FragmentDataListener {

    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        binding.run {
            fragment1Btn.setOnClickListener{
                // [1] Activity -> FirstFragment
                val dataToSend = "Hello First Fragment! \n From Activity"
                val fragment = FirstFragment.newInstance(dataToSend)
                setFragment(fragment)
            }

            fragment2Btn.setOnClickListener {
                // [1] Activity -> SecondFragment
                val dataToSend = "Hello Second Fragment!\n From Activity"
                val fragment = SecondFragment.newInstance(dataToSend)
                setFragment(fragment)
            }
        }

        setFragment(FirstFragment())
    }

    private fun setFragment(frag : Fragment) {
        supportFragmentManager.commit {
            replace(R.id.frameLayout, frag)
            setReorderingAllowed(true)
            addToBackStack("")
        }
    }

    // [3] SecondFragment -> Activity
    override fun onDataReceived(data: String) {
        // Fragment에서 받은 데이터를 처리
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show()
    }
}