안드로이드(코틀린) 채팅앱 만들기 - ChattingFragment 1

박준식·2022년 9월 1일
0

Catting

목록 보기
6/8
MainAcitivity의 3가지 탭 메뉴중 1가지인 ChattingFragment는 타이틀과 세팅 버튼이 포함된 toolbar와 채팅 가능한 고양이 목록이 나열된 recyclerView로 구성된다. 프래그먼트가 생성될때 MainActivity에서 사용자 정보를 받아오고 고양이 목록을 생성한다. 고양이 목록에 변경사항이 있으면 프래그먼트 재시작시 사용자 정보를 다시 받아온다. 각 리스트 아이템은 클릭하면 해당 고양이 정보를 기반으로 ChattingActivity가 시작된다. 본문에서는 프래그먼트에서 binding과 MainActivity의 변수를 사용하는 방법을 알아보고자 한다.

1. 전체 코드

  • fragment_chatting.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"
        android:background="@color/main_white"
        tools:context=".ChattingFragment">
    
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@color/main_white"
            android:minHeight="?attr/actionBarSize"
            android:theme="?attr/actionBarTheme"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:fontFamily="@font/bazzi"
                android:text="@string/main_catting_title"
                android:textColor="@color/main_black"
                android:textSize="24sp"
                tools:layout_editor_absoluteX="16dp"
                tools:layout_editor_absoluteY="15dp" />
        </androidx.appcompat.widget.Toolbar>
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/chattingRecycler"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@color/main_white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/toolbar" />
    
    
    </androidx.constraintlayout.widget.ConstraintLayout>
  • ChattingFragment.kt
  • package com.example.catting
    
    import android.content.Context
    import android.graphics.BitmapFactory
    import android.os.Bundle
    import android.util.Base64
    import android.util.Log
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.recyclerview.widget.LinearLayoutManager
    import androidx.recyclerview.widget.RecyclerView
    import com.example.catting.databinding.FragmentChattingBinding
    import com.example.catting.databinding.ItemChattingCatListBinding
    import io.socket.emitter.Emitter
    import org.json.JSONObject
    
    class ChattingFragment : Fragment() {
        lateinit var binding: FragmentChattingBinding
        lateinit var mainActivity: MainActivity
        lateinit var catList: ArrayList<CatProfile>
    
        override fun onAttach(context: Context) {
            super.onAttach(context)
            if(context is MainActivity) mainActivity = context
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            binding = FragmentChattingBinding.inflate(inflater, container, false)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            with(binding){
                toolbar.inflateMenu(R.menu.main_toolbar)
                toolbar.setOnMenuItemClickListener {
                    when (it.itemId) {
                        R.id.setting_icon -> {
                            mainActivity.openSettingActivity()
                            //mainActivity.openSettingActivity()
                            true
                        }
                        else -> false
                    }
                }
            }
        }
    
        override fun onResume() {
            Log.d("ChattingFragment","onResume")
            super.onResume()
            // 프래그먼트 재시작
            if(MainActivity.isChattingFragmentNeedRefresh){
                catList = mainActivity.userInfo.cats
                Log.d("ChattingFragment","$catList")
                binding.chattingRecycler.layoutManager = LinearLayoutManager(mainActivity,LinearLayoutManager.VERTICAL,false)
                binding.chattingRecycler.adapter = CatAdapter(catList)
                MainActivity.isChattingFragmentNeedRefresh = false
            }
            /*mainActivity.socket.emit("GetCatInfo","")
            mainActivity.socket.on("GetCatInfo",onGetCatInfo)*/
        }
    
        override fun onPause() {
            super.onPause()
            // 프래그먼트 전환
            Log.d("ChattingFragment","onPause")
        }
    }
    
    class CatAdapter(val listData: ArrayList<CatProfile>) : RecyclerView.Adapter<CatAdapter.Holder>(){
        class Holder(val binding: ItemChattingCatListBinding): RecyclerView.ViewHolder(binding.root){
            fun setCatProfile(catProfile: CatProfile){
                val decodedString = Base64.decode(catProfile.cPicture, Base64.DEFAULT)
                val decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.size)
                with(binding){
                    cName.text = catProfile.cName
                    chattingInfo.setOnClickListener {
                        MainActivity.getInstance()?.openChattingActivity(catProfile)
                    }
                    cImage.setImageBitmap(decodedByte)
                    cImage.clipToOutline = true
                    lastChat.text = "구현중"
                }
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
            val binding = ItemChattingCatListBinding.inflate(LayoutInflater.from(parent.context),parent,false)
            return Holder(binding)
        }
    
        override fun onBindViewHolder(holder: Holder, position: Int) {
            Log.d("ChattingFragment", "${listData[position]}")
            val catProfile = listData[position]
            holder.setCatProfile(catProfile)
        }
    
        override fun getItemCount() = listData.size
    }

2. 정리

  • 프래그먼트에서 MainActivity의 변수/함수 사용하기
  •   class ChattingFragment : Fragment() {
        lateinit var mainActivity: MainActivity
      	
      	...
    
        override fun onAttach(context: Context) {
            super.onAttach(context)
            if(context is MainActivity) mainActivity = context
        }
      	
      	...
      
      	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            Log.d("CattingFragment", "${mainActivity.userInfo}")
        }
    1. onAttach 함수의 파라미터인 context는 그 프래그먼트를 실행시킨 액티비티의 인스턴스가 담겨있다.
    2. 해당 context의 자료형이 MainActivity인지 확인하고 lateinit으로 선언한 mainActivity에 할당해주면 mainActivity.변수명 의 형태로 사용할 수 있다.
    3. 다른 Activity에서 프래그먼트를 생성해도 같은 방식으로 하면된다.

  • 프래그먼트에서 binding 사용하기
  •   class ChattingFragment : Fragment() {
        lateinit var binding: FragmentChattingBinding
      	
      	...
    
      	override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            binding = FragmentChattingBinding.inflate(inflater, container, false)
            return binding.root
        }
      
      	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
      		with(binding) {
      			...
      		}
        }
    1. onCreateView에서 lateinit으로 선언한 binding변수에 inflater를 넣고 binding.root를 반환하여 ContextView에 적용시킨다.

3. 주의사항

    • 에러코드
    • 발생경위
    • 원인
    • 해결방법

0개의 댓글