안드로이드 공부/ Fragment 실습

yellow·2021년 5월 29일
0

안드로이드 공부

목록 보기
14/28

📌 Fragment 만들기

📎 공통 과정

1. Fragment를 담을 Activity를 만든다.

  • ex) FragmentActivity.kt, activity_fragment.xml

2. Fragment를 만든다.

  • ex) Fragment1.kt, fragment1.xml

📎 Xml에 ViewComponent로 추가하기

3. Fragment를 담는 Activity에 <fragment>태그 추가

<fragment
        android:id="@+id/fragment1"
        android:name="com.example.myapplication.Fragment1"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        />
  • name 속성: 해당 <fragment>를 어떤 fragment로 쓸지 정해준다.
    2번에서 만든 fragment의 파일 경로를 넣어주면 된다.
  • id 속성: 다른 view들과 달리 "반드시" id를 정해주어야 한다.

4. Fragment를 그려주는 코드 작성

✔ onCreateView

  • view를 그리는 역할을 하는 생명주기
override fun onCreateView(
      inflater: LayoutInflater,
      container: ViewGroup?,
      savedInstanceState: Bundle?
): View? {
      // fragment1을 container에 그려넣는다.
      return inflater.inflate(R.layout.fragment1, container, false)
}
  • inflater의 역할 : view를 그려주는 역할을 한다. (inflate는 view를 리턴한다.)
  • container : 이 view를 갖다 놓을 곳, 부모view를 칭한다.

📎 코드로 추가하기 (동적으로 추가하기)

버튼을 누르면 fragment가 activity에 담기도록 하는 예제

3. Fragment를 담을 container 생성

  • container로 만들 수 있는 레이아웃은 부모뷰가 될 수 있는 레이아웃이다.
    (예: LinearLayout, RelativeLayout)
<LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@color/black"
        android:orientation="vertical"/>

4. Fragment를 가져오는 코드 작성

// fragment를 동적으로 작동하는 방법
// 1. fragment를 만든다
val fragment1 : Fragment1 = Fragment1()


val button: Button = findViewById(R.id.button)
button.setOnClickListener {

    val fragmentManager : FragmentManager = supportFragmentManager

    // Transaction
    // 작업의 단위 -> 시작과 끝이 있다
    val fragmentTransaction = fragmentManager.beginTransaction() // 트랜잭션을 시작하겠다.
    fragmentTransaction.replace(R.id.container, fragment1)
    fragmentTransaction.commit() // 트랜잭션을 끝낸다.
}
  • supportFragmentManager : 액티비티가 가지고있는 메소드, FragmentManager를 리턴한다.
  • replace(container, fragment) : 컨테이너 역할을 하는 뷰컴포넌트와 fragment를 바꾼다. 즉, fragment가 container 자리에 온다.

📌 Fragment 떼어내기

📎 동적으로 넣은 Fragment 떼어내기

val button2: Button = findViewById(R.id.button2)
    button2.setOnClickListener {
        val fragmentManager : FragmentManager = supportFragmentManager

        val fragmentTransaction = fragmentManager.beginTransaction()
        fragmentTransaction.detach(fragment1)
        // 혹은 fragmentTransaction.remove(fragment1)
        fragmentTransaction.commit()
}
  • detach() : 한번 fragment를 떼면 다시 붙일 수 없다.
  • remove() : 한번 fragment를 떼도 다시 붙일 수 있다.

❗주의할 점

  • 붙였던 fragment 객체를 떼어줘야 한다.

📌 Activity와 Fragment의 의사소통

📎 Activity에서 Fragment로 정보 보내기

  • argument와 bundle을 이용한다.

Activity에서

  • fragment 객체와 bundle객체를 만든다.
  • bundle 객체에 정보를 넣는다.
  • fragment객체에 정보가 담긴 bundle 객체에 끼워넣는다.
val fragment1 : Fragment1 = Fragment1()

// fragment에 data를 넣어주는 방법
// 1. bundle 객체를 만들어 정보를 넣는다.
val bundle : Bundle = Bundle()
bundle.putString("Hello", "hello")
// 2. 앞서 만든 bundle 객체를 fragment에 끼워넣는다.
fragment1.arguments = bundle

Fragment에서

override fun onActivityCreated(savedInstanceState: Bundle?) {
        // argument들을 꺼내옴
        val data = arguments?.getString("Hello")
        if (data != null) {
            Log.d("data", data)
        }

        super.onActivityCreated(savedInstanceState)
}

fragment에 정보가 전달되는 시점은 Transaction의 commit()이 수행되는 시점이다.
-> 따라서 정적으로 xml에 viewComponent로 추가한 경우에 data는 null값이다.

📎 Fragment에서 Activity로 정보 보내기

  • 시스템의 도움을 받을 수 없기 때문에 직접 구현해야 한다.
  • 리스너를 직접 구현
  1. 리스너 만들기 (fragment)
  2. 리스너 타입 변수 만들기 (fragment)
  3. context를 리스너 타입으로 형변환해서 2번에서 만든 변수에 담아서 사용(onAttach)
  4. 리스너에게 데이터 넣어주기 (onViewCreated)
  5. 리스너 내에 있는 메소드 구현하기 (activity)

Activity에서

  • fragment 클래스 내에 선언한 인터페이스를 implement해준다.
  • 그리고 인터페이스 내에 있는 메소드(리스너) override
package com.example.myapplication

import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentManager

class FragmentActivity : AppCompatActivity(), Fragment1.OndataPassListener {

    // 5. 리스너 (듣는 부분)
    override fun onDataPass(data: String?) {
        // fragment에서 data가 오면 Activity에서 처리해줘야하는 코드
        Log.d("pass",""+data)
    }
    
    ...
}

Fragment에서

  • 리스너 만들기 (fragment 클래스 외부에 파일로 만들어도 가능)
package com.example.myapplication

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment

class Fragment1 : Fragment(){

    // 1. 리스너 만들기
    interface OndataPassListener {
        fun onDataPass(data:String?)
    }

    // 2. 리스너 타입 변수 만들기
    lateinit var dataPassListener: OndataPassListener


    override fun onAttach(context: Context) {
        Log.d("life_cycle", "F onAttach")
        super.onAttach(context)
        // 3. context를 형변환해줌
        // Activity는 OndataPassListener를 implement한 것이라
        // context를 OndataPassListemenr로 형변환해서 사용 가능
        dataPassListener = context as OndataPassListener 
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        Log.d("life_cycle", "F onViewCreated")
        super.onViewCreated(view, savedInstanceState)

        // 4. 리스너에게 데이터를 넣어주는 역할을 하는 부분, onDataPass가 울리게 만듦
        val pass : Button = view.findViewById(R.id.pass)
        pass.setOnClickListener {
            dataPassListener.onDataPass("Good Bye")
        }
    }
    
    ...
}
profile
할 수 있어! :)

0개의 댓글