반응형

▶ Fragment(프래그먼트) 정의

 프래그먼트는 태블릿과 같은 대화면에서 효율적으로 화면을 구성하기 위해 생긴 구성요소입니다. 하지만 스마트폰과 같은 작은 화면에서도 효율적인 자원 활용과 메뉴 구성을 위해 종종 사용됩니다.

액티비티를 분할하여 화면의 한 부분을 정의하며 액티비티와 같이 레이아웃, 동작 처리, 생명주기를 가지는 독립적인 모듈인데요, 다른 액티비티에서도 사용할 수 있어 재사용성이 뛰어나며 액티비티 실행 중에 추가, 제거가 가능합니다.

프레그먼트는 액티비티의 일부분에만 배치되는 화면 및 동작을 조작하기 위한 객체입니다.  프레그먼트 매니저를 통해서 여러개의 프레그먼트를 조작할 수 있습니다. 레이아웃 xml 파일에서 다른 뷰들과 함께 배치될 수 있습니다.

▶ 프래그먼트 실습 :  버튼을 클릭하면 해당 프래그먼트 화면을 보여주기!

→  3개의 버튼과 3개의 프래그먼트 화면을 각각 만들고 각 버튼들을 클릭하면 각각의 프래그먼트 화면이 로딩 되도록 합니다. 이때 메인 레이아웃(activity_main.xml) 화면에는 FrameLayout을 이용하여 화면을 fragment를 로딩할 View 영역과 버튼을 클릭할 영역으로 구분해서 만들어 봅니다.

 

→ 각각의 프래그먼트 화면을 아래처럼 단순하게 배경색을 변경하여 구성하고, 추후에 이미지를 넣거나 다양하게 응용하면 됩니다.

 

▶  실행 결과 

→ 1번, 2번, 3번 버튼을 클릭하면 아래와 같이 main_activity.xml 레이아웃 화면에 각각의 프래그먼트 화면이 로딩되도록 합니다.

 

▶ 코드 구성

① 먼저 gradle에 있는 build.gradle.kts(Module :app) 파일에 아래처럼 뷰바인딩 사용 선언을 해주세요.


② 아래 이미지를 참고하여 res 》 layout 》 New 》 Fragment 》 Fragment(Blank) 를 클릭하고 타이틀은 frag1으로 입력하여 만들면 fragment_frag1.xml 파일과 함께 frg1.kt 파일이 세트로 만들어집니다. (layout에서 마우스 우클릭하면 New 메뉴가 나타납니다)

같은 방법으로 아래 이미지처럼  fragment_frag2.xml , fragment_frag3.xml ( frg2.kt , frag3.kt)을 만들어 주세요. 

 

→ frag 1의 xml 코드는 아래와 같습니다. (단순하게 배경색 지정하고 TextView를 하나 넣었습니다)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2233aa"
    tools:context=".frag1">

    <TextView
        android:id="@+id/txtview_frag1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text= "Frag 1 page"
        android:textSize="20dp"
        android:textStyle="bold"
        android:textColor="@color/white"/>

</FrameLayout>

 

frag1.xml의 뷰화면

→ frag2의 xml 코드 또한 동일하며 배경색과 id 그리고 text 내용만 각각 바꾸어 주세요.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#A51EB4"
    tools:context=".frag2">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text= "Frag 2 page"
        android:textSize="20dp"
        android:textStyle="bold"
        android:textColor="@color/white"/>

</FrameLayout>

frag2.xml의 뷰화면

 

→  frag3의 xml 코드 또한 동일하며 배경색과 id 그리고 text 내용만 각각 바꾸어 주세요.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF9800"
    tools:context=".frag3">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text= "Frag 3 page"
        android:textSize="20dp"
        android:textStyle="bold"
        android:textColor="@color/white"/>

</FrameLayout>

frag3.xml의 뷰화면

④ 자동으로 생성된 frag1.kt 프래그먼트의 클래스 함수 코드는 아래와 같습니다.

package com.example.fragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [frag1.newInstance] factory method to
 * create an instance of this fragment.
 */
class frag1 : Fragment() {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_frag1, container, false)
    }

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment frag1.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            frag1().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }
}

위 코드처럼 기본 생성된 코드 그대로 사용해도 실행에 문제는 없는데요,  필요 없는 내용 다 지우고 아래만 남겨 놓으면  됩니다.

package com.example.fragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

class frag1 : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_frag1, container, false)
    }
}

frag2.kt  와 frag3.kt 코드도 마찬가지로 정리해 보세요.

 

⑤ activity_main.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/main_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"></FrameLayout>

    <LinearLayout
        android:id="@+id/btn_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/main_view">

        <Button
            android:id="@+id/btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:text="1번"
            android:textSize="20dp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/btn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:text="2번"
            android:textSize="20dp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/btn3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:text="3번"
            android:textSize="20dp"
            android:textStyle="bold" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

⑥  뷰 바인딩을 적용한  MainActivity.kt의 코드는 아래처럼 해주세요. 

package com.example.fragment

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.fragment.databinding.ActivityMainBinding
import com.example.fragment.databinding.FragmentFrag1Binding

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)        
        setContentView(binding.root)
        binding.btn1.setOnClickListener {
            supportFragmentManager.beginTransaction().replace(R.id.main_view, frag1()).commit()
        }
        binding.btn2.setOnClickListener {
            supportFragmentManager.beginTransaction().replace(R.id.main_view, frag2()).commit()
        }
        binding.btn3.setOnClickListener {
            supportFragmentManager.beginTransaction().replace(R.id.main_view, frag3()).commit()
        }
    }
}

 

위 코드에서 supportFragmentManager 코드에도 바인딩 기능을 적용하면 아래와 같이 하면 됩니다. 
그리고, 각 버튼을 클릭할 때 마다 LinearLayout의 배경색도 따라 바뀌도록 아래처럼 코드를 추가해 줄 수 있어요.
"binding.linearBtnbox.setBackgroundColor(Color.parseColor("#2233aa"))"

package com.example.fragment

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.fragment.databinding.ActivityMainBinding
import com.example.fragment.databinding.FragmentFrag1Binding

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)        
        setContentView(binding.root)
        binding.btn1.setOnClickListener {
            binding.linearBtnbox.setBackgroundColor(Color.parseColor("#2233aa"))
            supportFragmentManager.beginTransaction().replace(binding.frameLayout.id, frag1()).commit()
        }
        binding.btn2.setOnClickListener {
            binding.linearBtnbox.setBackgroundColor(Color.parseColor("#A51EB4"))
            supportFragmentManager.beginTransaction().replace(binding.frameLayout.id, frag2()).commit()
        }
        binding.btn3.setOnClickListener {
            binding.linearBtnbox.setBackgroundColor(Color.parseColor("#FF9800"))
            supportFragmentManager.beginTransaction().replace(binding.frameLayout.id, frag3()).commit()
        }
    }
}

 

이렇게 까지만 하면 작성이 완료되고 실행해 보면 아래와 같이 실행이 되는 것을 볼 수 있습니다.

 

마지막으로, 살짝 응용해서 TextView 대신 이미지 뷰(ImageView)를 넣어 사진을 보여주는 것으로 바꾸어 볼게요.

그럼, 변경할 곳은 fragment_frag1.xml  파일에서 TextView 대신 아래와 같이 ImageView 를 대체해서 넣어 주면 됩니다.   나머지 fragment_frag2.xml 과 fragment_frag3.xml 파일도 동일하게 바꾸어주세요.

<fragment_frag1.xml 파일 코드>

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffaaff"
    tools:context=".frag1">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@drawable/lake1"
        android:background="#22aabb" />

</FrameLayout>

이때, 보여줄 사진으로 호수(lake)사진을 넣었는데요, 첨부해 드릴테니 연습으로 해보세요.

호수(jpg).zip
1.53MB


사진 파일들은  안드로이드 스튜디오의 프로젝트 탐색창에서 ,  res 》 drawable 폴더로 복사해 넣어주세요. 
(아래 참고)  직접 끌어다 넣기하거나 , 복붙해도 됩니다.

아래는, 이미지로 대체해서 실행한 모습입니다. 
사진이 없는 배경의 공간은 기본값인 흰색인데, background 배경의 색을 사진과 잘 어울리게 넣어서 채워봤습니다.

 

그럼, 지금까지 안드로이드 스튜디오에서  kotlin으로 프래그먼트(fragment)를 사용하는 방법과 실제 예시를 설명해 드렸습니다.  몇 번 반복적으로 연습해 보면 금방 응용할 수 있을 거예요. 

감사합니다.

반응형