본문 바로가기
개발노트/Kotlin

7주차 2일 activity->frament 그리고 adapter

by 시계속세상은아직돌아가는중 2023. 8. 22.

1. 코드의 구조

package com.example.class2_homework.todo

import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.class2_homework.R
import com.example.class2_homework.databinding.TodoaddActivityBinding
import com.example.class2_homework.main.MainActivity
import com.example.class2_homework.todo.TodoFragment
import com.example.class2_homework.todo.TodoModel

class TodoaddActivity : AppCompatActivity() {

    private lateinit var biding:TodoaddActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.todoadd_activity)

        biding = TodoaddActivityBinding.inflate(layoutInflater)
        setContentView(biding.root)

        initView()


    }

    private fun initView() = with(biding){


        todoaddBtnBack.setOnClickListener{
            finish()
        }
        todoaddBtnOk.setOnClickListener{
            val title = todoaddEditTitle.text.toString()
            val detail = todoaddEditDetail.text.toString()

            val intent = Intent(this@TodoaddActivity,MainActivity::class.java)
            intent.putExtra("title", title)
            intent.putExtra("detail", detail)

            startActivity(intent)
        }
    }
}

플러팅 버튼이 눌리면 나오는 액티비티

메인 액티비티로 인텐트를 전달한다.

 

package com.example.class2_homework.main


import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager2.widget.ViewPager2
import com.example.class2_homework.R
import com.example.class2_homework.bookmark.BookmarkFragment
import com.example.class2_homework.databinding.MainActivityBinding
import com.example.class2_homework.todo.TodoFragment
import com.example.class2_homework.todo.TodoaddActivity
import com.google.android.material.tabs.TabLayoutMediator

class MainActivity : AppCompatActivity() {

    private lateinit var binding: MainActivityBinding
    private val getTitle by lazy { intent.getStringExtra("title") ?: "제목" }
    private val getDetail by lazy { intent.getStringExtra("detail") ?: "내용" }

    private val viewPagerAdapter by lazy {
        MainViewPagerAdapter(this@MainActivity,title = getTitle, detail = getDetail)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = MainActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initView()

        if(getTitle != " 제목" && getDetail != "내용"){
            Toast.makeText(this, "제목 : ${getTitle} 내용 : ${getDetail}", Toast.LENGTH_SHORT).show()
        }

    }


    private fun initView() = with(binding) {
        toolBar.title = getString(R.string.app_name)

        viewPager.adapter = viewPagerAdapter


        // TabLayout x ViewPager2
        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.setText(viewPagerAdapter.getTitle(position))
        }.attach()

        viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageSelected(position: Int) {
                if (position == getBookmarkFragment()) {
                    fabAddTodo.hide()
                } else {
                    fabAddTodo.show()
                }
            }
        })
        // fab
        fabAddTodo.setOnClickListener {
            var intent = Intent(this@MainActivity, TodoaddActivity::class.java)
            startActivity(intent)
        }
    }

    private fun getBookmarkFragment(): Int {

        for (i in 0 until viewPagerAdapter.itemCount) {
            if (viewPagerAdapter.createFragment(i) is BookmarkFragment) {
                return i
            }
        }
        return -1
    }

}

 

매인 액티비티에서 플러팅 버튼을 누를 시 나오는 'Todoadd'로 가서 정보를 전달받는다.

private val getTitle by lazy { intent.getStringExtra("title") ?: "제목" }
private val getDetail by lazy { intent.getStringExtra("detail") ?: "내용" }

 

해당 변수들은 아래의 어댑터를 사용하기 위해 지연초기화를 사용하였다.

 

해당 값들이 존재하지 않는 최초 실행 시 null 값이 아닌 초기 default value를 넣어준다.

?:는 앨비스 연산자로, 해당 값이 null된다면 옆의 값이 들어간다

 

여기서 재밌는건 엘비스 프레슬리의 머리스타일처럼 생겼다고 해서 붙여진 연산자다

 

 

class MainViewPagerAdapter(
    fragmentActivity: FragmentActivity,
    private val title: String,
    private val detail: String
) : FragmentStateAdapter(fragmentActivity) {

    private val fragments = ArrayList<MainTabs>()

    init {
        fragments.add(
            MainTabs(TodoFragment.newInstance(title, detail), R.string.main_tab_todo_title)
        )
        fragments.add(
            MainTabs(BookmarkFragment.newInstance(), R.string.main_tab_bookmark_title),
        )
    }

    fun getTitle(position: Int): Int {
        return fragments[position].titleRes
    }

    override fun getItemCount(): Int {
        return fragments.size
    }

    override fun createFragment(position: Int): Fragment {
        return fragments[position].fragment
    }



}

해당 값을 전달해주기 위해서 adapter에 넣어준다.

 

  fragments.add(
            MainTabs(TodoFragment.newInstance(title, detail), R.string.main_tab_todo_title)
        )

해당 값들을 넘겨주기 위해 newInstance에 해당값을 넣었으며 이는

 

    private val viewPagerAdapter by lazy {
        MainViewPagerAdapter(this@MainActivity,title = getTitle, detail = getDetail)
    }

메인 액티비티에서도 확인이 가능하다.

 

package com.example.class2_homework.todo

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.class2_homework.databinding.TodoFragmentBinding


class TodoFragment : Fragment() {

    companion object {
        fun newInstance(title: String, detail: String): TodoFragment {
            val fragment = TodoFragment()
            val args = Bundle()
            args.putString("title", title)
            args.putString("detail", detail)
            fragment.arguments = args
            return fragment
        }
    }

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

    private val listAdapter by lazy {
        TodoListAdapter()
    }

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

        val title = arguments?.getString("title")?:"제목"
        val detail = arguments?.getString("detail")?:"내용"

//        val testList = mutableListOf<TodoModel>()
        val todoList = TodoListDB.todoListDB

        if (title != "제목" && detail != "내용") {
            val todoModel = TodoModel(id=todoList.size ,"${todoList.size+1}.${title}", detail)
            todoList.add(todoModel)

            listAdapter.addItems(todoList)
            listAdapter.notifyDataSetChanged()

        }




    }



    private fun initView() = with(binding) {
        todoList.adapter = listAdapter
    }

    override fun onDestroyView() {
        _binding = null
        super.onDestroyView()
    }
}

Todofrafment를 살펴보자

 

    companion object {
        fun newInstance(title: String, detail: String): TodoFragment {
            val fragment = TodoFragment()
            val args = Bundle()
            args.putString("title", title)
            args.putString("detail", detail)
            fragment.arguments = args
            return fragment
        }
    }

Todofragment에서 newInstance를 받을 준비를 하고

 

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

        val title = arguments?.getString("title")?:"제목"
        val detail = arguments?.getString("detail")?:"내용"

//        val testList = mutableListOf<TodoModel>()
        val todoList = TodoListDB.todoListDB

        if (title != "제목" && detail != "내용") {
            val todoModel = TodoModel(id=todoList.size ,"${todoList.size+1}.${title}", detail)
            todoList.add(todoModel)

            listAdapter.addItems(todoList)
            listAdapter.notifyDataSetChanged()

        }

해당 값을 onViewCreated에 선언하여 그려질 수 있도록 한다.

또한 null값이 들어가지 않도록 해당 값의 더미 데이터를 지정해주며 이는 메인 액티비티에서 지정한 값과 동일하게 지정해주었다. 이유는 아래 if문을 작동시키기 위해였다.

 

     if (title != "제목" && detail != "내용") {
            val todoModel = TodoModel(id=todoList.size ,"${todoList.size+1}.${title}", detail)
            todoList.add(todoModel)

            listAdapter.addItems(todoList)
            listAdapter.notifyDataSetChanged()

        }
package com.example.class2_homework.todo


data class TodoModel(
    val id :Int,
    val title: String,
    val detail : String
)
package com.example.class2_homework.todo

object TodoListDB {

    val todoListDB = mutableListOf<TodoModel>()
}

 

해당 값들이 저장될 수 있도록 objec tclass에서 관리를 해주며

id는 현재 사이즈값 +1을 해주면 해당 번째에 해당하므로(add하기 전에는 현재 아무런 값이 들어가 있지 않으므로 리스트의 사이즈는 0) .size+1을 해줬다.

 

 

listAdapter.notifyDataSetChanged()

이후 해당 코드를 통해서 변화를 감지하여 프래그먼트를 새로 그리게 만든다.

 

 

참고 블로그

https://aries574.tistory.com/287

 

[안드로이드] 액티비티(Activity) 에서 프래그먼트(Fragment) 데이터 전달하는 방법

이번 시간에는 액티비티(Activity)에서 프래그먼트(Fragment)로 데이터 전달하는 방법에 대하여 알아보겠습니다. 목차 1. 실행 화면 2. 프래그먼트 만들기 3. 메인 화면 구성 activity_main.xml 4. 메인 코드

aries574.tistory.com

https://parkho79.tistory.com/155

 

RecyclerView (6) - RecyclerView item 추가, 수정, 삭제

이번 포스팅에서는 하단 그림과 같이 RecyclerView item 을 동적으로 추가, 수정, 삭제 하는 방법을 알아보자. 참고로, 지난 포스팅에서는 RecyclerView 에 image + text 출력, click 처리, menu 출력 하는 방법에

parkho79.tistory.com