Q : FAB를 눌러서 Todo 추가 화면을 노출 시키고, 제목과 내용을 입력해서 “Todo” 탭에 반영
1. requireActivity() 사용
MainActivity
- fabAdd 버튼 눌러 TodoActivity로 이동
class MainActivity : AppCompatActivity() {
private lateinit var binding: MainActivityBinding
private val viewPagerAdapter by lazy {
MainViewPagerAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
initView()
}
private fun initView() = with(binding) {
toolBar.title = getString(R.string.app_name)
viewPager.adapter = viewPagerAdapter
// FloatingActionButton 숨기기
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
// 페이지가 선택되었을 때 호출됩니다.
super.onPageSelected(position)
if(position == 0){
binding.fabAddTodo.show()
}else{
binding.fabAddTodo.hide()
}
}
})
// TabLayout x ViewPager2
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.setText(viewPagerAdapter.getTitle(position))
}.attach()
// fab
fabAddTodo.setOnClickListener {
val intent = Intent(it.context, TodoAddActivity::class.java)
startActivity(intent)
}
}
}
TodoAddActivity
- 입력받은 제목과 내용 데이터를 MainActivity로 보냄
class TodoAddActivity : AppCompatActivity() {
private lateinit var binding: TodoAddActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = TodoAddActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar2)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.title = "할 일"
binding.toolbar2.setNavigationOnClickListener{
finish()
}
binding.btnAdd.setOnClickListener {
val title = binding.etTitle.text.toString()
val content = binding.etContent.text.toString()
val mainActivityIntent = Intent(this, MainActivity::class.java)
mainActivityIntent.putExtra("title", title)
mainActivityIntent.putExtra("content", content)
startActivity(mainActivityIntent)
finish()
}
}
}
TodoFragment
- requireActivity를 사용해 MainActivity에 전달된 데이터를 Fragment에서도 받아옴 (MainActivity와 연결되어있어 가능)
- testList 넣은 뒤 어댑터의 addItems 함수로 연결
class TodoFragment : Fragment() {
companion object {
const val TAG = "TodoFragment"
fun newInstance() = TodoFragment()
}
private var _binding: TodoFragmentBinding? = null
private val binding get() = _binding!!
private val listAdapter by lazy {
TodoListAdapter()
}
val testList = arrayListOf<TodoModel>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = TodoFragmentBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
// 데이터 가져오기 (MainActivity가 받아온 데이터)
val titleText = requireActivity().intent.getStringExtra("title")
val content = requireActivity().intent.getStringExtra("content")
if (!titleText.isNullOrEmpty()) {
if (content != null) {
testList.add(TodoModel(titleText, content))
}else{
testList.add(TodoModel(titleText, ""))
}
}
listAdapter.addItems(testList)
}
private fun initView() = with(binding) {
todoList.adapter = listAdapter
}
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}
TodoListAdapter
- 받아온 리스트를 Adapter용 list에 추가
- notifyDataSetChanged()를 통해 새롭게 업데이트된 데이터 보여줌
private val list = ArrayList<TodoModel>()
class TodoListAdapter : RecyclerView.Adapter<TodoListAdapter.ViewHolder>() {
fun addItems(items: List<TodoModel>) {
list.addAll(items)
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return list.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
TodoItemBinding.inflate(LayoutInflater.from(parent.context))
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = list[position]
holder.bind(item)
}
class ViewHolder(
private val binding: TodoItemBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: TodoModel) = with(binding) {
title.text = item.title
content.text = item.content
}
}
}
TodoModel
data class TodoModel(
val title: String,
val content: String,
)
2. registerForActivityResult, MainActivityAdapter에서 Fragment 가져오기
MainActivity
- fabAdd 버튼 눌러 TodoActivity로 이동
- registerForActivityResult 사용해 데이터 받아오기
class MainActivity : AppCompatActivity() {
private lateinit var binding: MainActivityBinding
private val viewPagerAdapter by lazy {
MainViewPagerAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
initView()
}
private fun initView() = with(binding) {
toolBar.title = getString(R.string.app_name)
viewPager.adapter = viewPagerAdapter
//registerForActivityResult 사용해 데이터 받아오기
val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result ->
if(result.resultCode == Activity.RESULT_OK){
val titleText = result.data?.getStringExtra("title").toString()
val content = result.data?.getStringExtra("content").toString()
// fragment 받아온 뒤 fragment 함수인 addList 사용
val todoFragment = viewPagerAdapter.getTodoFragment() as TodoFragment
if (titleText != null) {
if (content != null) {
todoFragment.addList(titleText, content) // titleText와 content를 전달하여 호출
} else {
todoFragment.addList(titleText, "") // titleText만 전달하여 호출
}
}
}
}
// FloatingActionButton 숨기기
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
// 페이지가 선택되었을 때 호출됩니다.
super.onPageSelected(position)
if(position == 0){
binding.fabAddTodo.show()
}else{
binding.fabAddTodo.hide()
}
}
})
// TabLayout x ViewPager2
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.setText(viewPagerAdapter.getTitle(position))
}.attach()
// fab
fabAddTodo.setOnClickListener {
val intent = Intent(it.context, TodoAddActivity::class.java)
resultLauncher.launch(intent)
}
}
}
TodoAddActivity
- 입력받은 제목과 내용 데이터를 MainActivity로 보냄
class TodoAddActivity : AppCompatActivity() {
private lateinit var binding: TodoAddActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = TodoAddActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar2)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.title = "할 일"
binding.toolbar2.setNavigationOnClickListener{
finish()
}
binding.btnAdd.setOnClickListener {
val title = binding.etTitle.text.toString()
val content = binding.etContent.text.toString()
// RESULT_OK 결과코드와 데이터 보냄
intent.putExtra("title", title)
intent.putExtra("content", content)
setResult(RESULT_OK, intent)
finish()
}
}
}
MainViewPagerAdapter
- fragments 리스트 순서 0번째인 TodoFragment 리턴
- TodoFragment 가져오는 함수 이용해 다른 액티비티에서도 TodoFragment를 연결할 수 있다.
class MainViewPagerAdapter(
fragmentActivity: FragmentActivity
) : FragmentStateAdapter(fragmentActivity) {
private val fragments = ArrayList<MainTabs>()
init {
fragments.add(
MainTabs(TodoFragment.newInstance(), "Todo")
)
fragments.add(
MainTabs(BookmarkFragment.newInstance(), "Bookmark"),
)
}
//TodoFragment 가져오는 함수
fun getTodoFragment() : Fragment{
return fragments[0].fragment
}
fun getTitle(position: Int): String {
return fragments[position].titleRes
}
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position].fragment
}
}
TodoFragment
- addList 함수 생성해 listAdapter의 addItems 함수 불러옴
- addItems 함수 사용해 adapter 안에 있는 list에 새로운 TodoModel 객체 추가 시킴
class TodoFragment : Fragment() {
companion object {
const val TAG = "TodoFragment"
fun newInstance() = TodoFragment()
}
private var _binding: TodoFragmentBinding? = null
private val binding get() = _binding!!
private val listAdapter by lazy {
TodoListAdapter()
}
val testList = arrayListOf<TodoModel>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = TodoFragmentBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
//listAdatper의 함수인 addItems 연결해 adapter list에 추가시킴
fun addList(title:String, content:String){
listAdapter.addItems(TodoModel(title, content))
}
private fun initView() = with(binding) {
todoList.adapter = listAdapter
}
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}
TodoFragment
- 객체를 하나하나 받기 위해 인자 값을 변경해줌
class TodoListAdapter : RecyclerView.Adapter<TodoListAdapter.ViewHolder>() {
private val list = ArrayList<TodoModel>()
// 인자 값 변경 : List<TodoModel> -> TodoModel
fun addItems(items: TodoModel) {
list.add(items)
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return list.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
TodoItemBinding.inflate(LayoutInflater.from(parent.context))
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = list[position]
holder.bind(item)
}
class ViewHolder(
private val binding: TodoItemBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: TodoModel) = with(binding) {
title.text = item.title
content.text = item.content
}
}
}
MainActivity
- viewPagerAdapter.getTodoFragment() as TodoFragment : TodoFragment 가져오기
- todoFragment.addList(titleText, content) : titleText와 content를 Fragment에 전달하여 호출
class MainActivity : AppCompatActivity() {
private lateinit var binding: MainActivityBinding
private val viewPagerAdapter by lazy {
MainViewPagerAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
initView()
}
private fun initView() = with(binding) {
toolBar.title = getString(R.string.app_name)
viewPager.adapter = viewPagerAdapter
//registerForActivityResult 사용해 데이터 받아오기
val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result ->
if(result.resultCode == Activity.RESULT_OK){
val titleText = result.data?.getStringExtra("title").toString()
val content = result.data?.getStringExtra("content").toString()
// fragment 받아온 뒤 fragment 함수인 addList 사용
val todoFragment = viewPagerAdapter.getTodoFragment() as TodoFragment
if (titleText != null) {
if (content != null) {
todoFragment.addList(titleText, content) // titleText와 content를 전달하여 호출
} else {
todoFragment.addList(titleText, "") // titleText만 전달하여 호출
}
}
}
}
// FloatingActionButton 숨기기
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
// 페이지가 선택되었을 때 호출됩니다.
super.onPageSelected(position)
if(position == 0){
binding.fabAddTodo.show()
}else{
binding.fabAddTodo.hide()
}
}
})
// TabLayout x ViewPager2
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.setText(viewPagerAdapter.getTitle(position))
}.attach()
// fab
fabAddTodo.setOnClickListener {
val intent = Intent(it.context, TodoAddActivity::class.java)
resultLauncher.launch(intent)
}
}
}
'Android' 카테고리의 다른 글
Fragment (0) | 2023.08.24 |
---|---|
뷰 바인딩 (0) | 2023.08.24 |
View와 ViewGroup (2) | 2023.08.10 |
Recycler View (0) | 2023.08.10 |
TabLayout과 ViewPager2 연결하기 (0) | 2023.08.09 |