* 이 글은 인프런 강의 <[왕초보편] 앱 8개를 만들면서 배우는 안드로이드 코틀린>을 보고 정리한 글입니다.
목표
네비게이션을 이용하여 가수를 선택하고
리사이클러뷰를 통해 각 가수의 노래 리스트들을 나타내자
1. 네비게이션(Navigation) 만들기
app 폴더에서 New > Android Resource File 클릭
리소스 타입을 네비게이션으로 설정하고 파일을 생성한다.
2. activity_main.xml에서 네비게이션 기능 넣기
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/trot_nav"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
android:layout_width="match_parent"
android:layout_height="match_parent"
레이아웃의 크기를 전체크기로 지정한다.
3. 프래그먼트(Fragment) 만들기
New > Fragment > Fragment(Blank)를 클릭한다.
Singer1Fragment, Singer2 Fragment , Singer3 Fragment를 생성한다.
4. 네비게이션에서 프래그먼트들 간의 연결 지정
네비게이션(trot_nav.xml)에서 프래그먼트들을 추가한다.
5. fragment_singer(1, 2, 3).xml
각 프래그먼트 xml 파일에서 앱 하단의 세 가수들의 버튼, 가수의 이름, 리사이클러뷰를 만든다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Singer1Fragment">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:gravity="center"
android:text="영탁노래 리스트"
android:background="@color/black"
android:textColor="@color/white"
android:textSize="30sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="10dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/singRV"
android:layout_marginTop="70dp"
android:layout_marginBottom="80dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
app:layout_constraintBottom_toBottomOf="parent">
<ImageView
android:id="@+id/image1"
android:src="@drawable/photo1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:layout_weight="1" />
<ImageView
android:id="@+id/image2"
android:src="@drawable/photo2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:layout_weight="1"/>
<ImageView
android:id="@+id/image3"
android:src="@drawable/photo3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:layout_weight="1"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
ConstraintLayout으로 설정한다.
app:layout_constraintBottom_toBottomOf="parent"
버튼을 맨 밑에 붙게 한다.
6. Singer(1, 2, 3) Fragment
버튼 클릭에 따라 프래그먼트를 바꾸도록 한다.
class Singer1Fragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
val view = inflater.inflate(R.layout.fragment_singer1, container, false)
view.findViewById<ImageView>(R.id.image2).setOnClickListener {
it.findNavController().navigate(R.id.action_singer1Fragment_to_singer2Fragment)
}
view.findViewById<ImageView>(R.id.image3).setOnClickListener {
it.findNavController().navigate(R.id.action_singer1Fragment_to_singer3Fragment)
}
return view
}
}
val view = inflater.inflate(R.layout.fragment_singer1, container, false)
view 변수에 fragment_singer1 레이아웃을 넣는다.
view.findViewById<ImageView>(R.id.image2).setOnClickListener {
fragment_singer1의 ImageView image2 부분이 클릭됐을 때
it.findNavController().navigate(R.id.action_singer1Fragment_to_singer2Fragment)
singer1Fragment에서 singer2Fragment로 이동한다. (네비게이션 사용)
7. rv_item.xml
리사이클러뷰에서 각 요소들이 어떻게 레이아웃 될지를 구성한다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/rvTextId"
android:text="노래리스트"
android:textSize="25sp"
android:layout_margin="10dp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
LinearLayout으로 변경
android:id="@+id/rvTextId"
TextView의 아이디 값을 rvTextId로 한다.
8. RVAdapter
리사이클러뷰의 어댑터를 만든다.
class RVAdapter (val items: MutableList<String>) : RecyclerView.Adapter<RVAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.rv_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: RVAdapter.ViewHolder, position: Int) {
holder.bindItems(items[position])
}
override fun getItemCount(): Int {
return items.size
}
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(item : String) {
val rv_text = itemView.findViewById<TextView>(R.id.rvTextId)
rv_text.text = item
}
}
}
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
뷰홀더를 만들어준다.
val rv_text = itemView.findViewById<TextView>(R.id.rvTextId)
프래그먼트 파일에서의 뷰에 대하여 rvTextId를 변수로 갖는다.
rv_text.text = item
rv_text의 텍스트 값을 item들로 구성한다.
9. Singer(1, 2, 3) Fragment
노래목록들을 만들고(items), 데이터를 어댑터에 전달하여 그 반환값을 리사이클러뷰 레이아웃에 적용시킨다.
class Singer1Fragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_singer1, container, false)
val items = mutableListOf<String>()
items.add("니가 왜 거기서 나와")
items.add("이불")
items.add("찐이야")
items.add("비상")
items.add("니가 왜 거기서 나와")
items.add("이불")
items.add("찐이야")
items.add("비상")
items.add("니가 왜 거기서 나와")
items.add("이불")
items.add("찐이야")
items.add("비상")
items.add("니가 왜 거기서 나와")
items.add("이불")
items.add("찐이야")
items.add("비상")
val rv = view.findViewById<RecyclerView>(R.id.singRV)
val rvAdapter = RVAdapter(items)
rv.adapter = rvAdapter
rv.layoutManager = LinearLayoutManager(context)
view.findViewById<ImageView>(R.id.image2).setOnClickListener {
it.findNavController().navigate(R.id.action_singer1Fragment_to_singer2Fragment)
}
view.findViewById<ImageView>(R.id.image3).setOnClickListener {
it.findNavController().navigate(R.id.action_singer1Fragment_to_singer3Fragment)
}
return view
}
}
val items = mutableListOf<String>()
items.add("니가 왜 거기서 나와")
노래 데이터 값을 만든다.
val rv = view.findViewById<RecyclerView>(R.id.singRV)
뷰에서 리사이클러뷰를 찾아 rv라는 변수로 선언한다.
val rvAdapter = RVAdapter(items)
데이터들을 어댑터에 전달한다.
rv.adapter = rvAdapter
어댑터에서 반환한 값을 리사이클러뷰와 연결시킨다.
rv.layoutManager = LinearLayoutManager(context)
리사이클러뷰가 작동되도록 한다.