반응형
Greensky0026
삽질러의 대환장 공사판
Greensky0026
전체 방문자
오늘
어제
  • 분류 전체보기 (241)
    • Language (56)
      • JAVA (13)
      • Swift (38)
      • Kotlin (4)
      • Dart (0)
      • PHP (0)
      • JavaScript (1)
    • IDE & Framework (92)
      • Spring (10)
      • Android (48)
      • iOS (8)
      • NodeJS (1)
      • CodeIgniter (3)
      • Flutter (1)
      • 분류중 (18)
    • Infra (8)
    • Database (12)
    • VCS (4)
    • Debug Log (34)
      • java (7)
      • swift (3)
      • Android (9)
      • Web (7)
      • 삽질기 (7)
    • Others (19)
      • 코딩테스트 풀이 (0)
      • IT 이야기 (18)
    • 쉼터 (2)
    • 개발공부 (14)
      • Network (1)
      • 자료구조와 알고리즘 (2)
      • Code design (8)
      • ETC (1)
      • 아카이브 (1)

블로그 메뉴

    공지사항

    • 프로그래머스 코딩 테스트 관련글 비공개 처리

    인기 글

    태그

    • Android
    • Java
    • swift
    • swfit
    • level1
    • 프로그래머스
    • 타입
    • reduce
    • JSP
    • xcode
    • 구축
    • IT
    • map
    • 공부
    • 개발
    • 코딩테스트
    • 예제
    • ios
    • kotlin
    • 프로그래밍

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    Greensky0026
    IDE & Framework/Android

    [Kotlin] Fragment (2) - 기초 예제

    [Kotlin] Fragment (2) - 기초 예제
    IDE & Framework/Android

    [Kotlin] Fragment (2) - 기초 예제

    2021. 12. 19. 13:04
    반응형

    * 본 예제는 간단히 ViewBinding을 사용합니다

    https://greensky0026.tistory.com/190

     

    View binding 사용해보기

    findbyviewid를 쓰지 않아도 되게 해줘서 코드가 매우 간결해집니다. app level gradle //build.gradle android{ //... viewBinding { enabled = true } } //... } replace Acitivity - onCreate : setContentView..

    greensky0026.tistory.com


    개요

    본 예저는 간단히 fragment를 버튼을 클릭해 swap해 보여주는 Application 입니다.

    MainActivity는 main, another 버튼이 존재하며 클릭시 해당 fragment를 swap해 보여줍니다.

     

    구성

    MainActivity.kt

    activity_main.mxl

    MainHomeFragment.kt

    fragment_main_home.xml

    MainAnotherFragment.kt

    fragment_main_another.xml

     

    1. MainActivity.kt

    변수 선언

    val b by lazy {
    ActivityMainBinding.inflate(layoutInflater)
    }
    
    private val fragmentManager by lazy {
    	supportFragmentManager
    }
    
    private val homeFragment by lazy {
    	MainHomeFragment()
    }
    
    private val anotherFragment by lazy {
    	MainAnotherFragment()
    }
    
    private lateinit var transaction: FragmentTransaction
    private var nowFragment: Fragment? = null

    by lazy를 사용해 val 변수들을 호출시에 초기화 해주두록 세팅했습니다.

    fragmentManager와 각 fragment들을 var변수로 선언했습니다.

     

    transaction은 프레그먼트를 추가, 제거 및 교체를 할 수 있습니다. 자세한 사항은 여기를 참조하세요.

    여기서는 단순 교체작업용 만으로 사용합니다.

    nowFragment는 현재 보여지고 있는 fragment로 교채를 요청했을 때, 이벤트 발생을 위해 선언했습니다.

     

     override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(b.root)
       replaceTransaction(homeFragment)
    
      b.btnPresentMainFragment.setOnClickListener {
          replaceTransaction(homeFragment)
      }
      b.btnPresentAnotherFragment.setOnClickListener {
          replaceTransaction(anotherFragment)
      }
    }

     

     버튼을 세팅하고, replaceTransaction 함수를 homeFragment를 매개변수로 넣어서 호출햇습니다.

    이름에서 보듯이 해당 함수는 fragment를 swap해주는 함수입니다. 

     

    private fun replaceTransaction(fragment: Fragment){
      if(nowFragment == fragment){
        Toast.makeText(this, "이미 해당 Fragment를 보여주고 있습니다.", Toast.LENGTH_SHORT).show()
        return
      }
      transaction = fragmentManager.beginTransaction()
      transaction.replace(b.flFlagmentContainer.id, fragment).commitAllowingStateLoss()
      nowFragment = fragment
    }

    교체시 nowFragment에 현재 fragment를 확인해 같은 프래그먼트라면 교체작업을 진행하지 않고 토스트로 명시 후 작업을 종료합니다.

    교체시엔 beginTransaction()호출 후 작업을 명시한 후에 commitAllowingStateLoss를 호출하면 됩니다.

    트랜젝션을 시작 후 커밋해야 하다니, 약간은 db 명령어 같죠? ㅎㅎ

    교체또한 replace에 fragment를 담을 container view와 framgent객채만 입력해주면 됩니다.

     

    2. activity_main.mxl

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        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=".MainActivity"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:orientation="horizontal">
            <View
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="0dp"/>
            <Button
                android:id="@+id/btn_present_main_fragment"
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:text="main"/>
            <Button
                android:id="@+id/btn_present_another_fragment"
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:text="another"/>
            <View
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="0dp"/>
        </LinearLayout>
        <FrameLayout
            android:id="@+id/fl_flagment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>

    간단히 버튼 두개와 프래그먼트를 출력할 FramLayout으로 구성되어 잇습니다.

     

    3. MainHomeFragment.kt

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

    우선은 변수선언부터 해줍니다. view binding을 할 것이므로 초기화 해 주고,

    override fun onCreate(savedInstanceState: Bundle?) {
    	super.onCreate(savedInstanceState)
    }
    
    override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {
      _binding = FragmentMainHomeBinding.inflate(inflater, container, false)
      return binding.root
    }

    onCreateView로 view를 그리기 전, 그릴 bingding 객체를 inflate하여 _binding에 저장하고 반환합니다.

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

    위와같이 작업한다면, 메모리 누수를 방지하기 위해 onDestroy에 꼭!!! _binding을 초기화 해주어야 합니다.

    이런 일련의 작업이 불편하다면, androidx.lifecycle을 사용해 편하게 작성할 수 잇습니다. 여기를 참고하세요.

    4. fragment_main_home.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainHomeFragment"
        android:background="#FFEFEF">
    
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Home Flagment"
            android:textSize="40dp"
            android:textColor="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    Fragment를 구분하기 위해 배경색과 text를 입력해뒀습니다.

    MainAnotherFragment.kt와 fragment_main_another.xml도 같은 형식이니 생략하겠습니다.

    궁금하시다면 아래 전체 코드보기로 봐주세요 ㅎㅎ

     

    결과

     

     

     


    전체 코드 보기

    https://github.com/gr2nsky/FlagmentPactice

     

    GitHub - gr2nsky/FlagmentPactice

    Contribute to gr2nsky/FlagmentPactice development by creating an account on GitHub.

    github.com

    MainActivity

    더보기
    class MainActivity : AppCompatActivity() {
    
        val b by lazy {
            ActivityMainBinding.inflate(layoutInflater)
        }
    
        private val fragmentManager by lazy {
            supportFragmentManager
        }
    
        private val homeFragment by lazy {
            MainHomeFragment()
        }
    
        private val anotherFragment by lazy {
            MainAnotherFragment()
        }
    
        private lateinit var transaction: FragmentTransaction
        private var nowFragment: Fragment? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(b.root)
            replaceTransaction(homeFragment)
    
            b.btnPresentMainFragment.setOnClickListener {
                replaceTransaction(homeFragment)
            }
            b.btnPresentAnotherFragment.setOnClickListener {
                replaceTransaction(anotherFragment)
            }
        }
    
        private fun replaceTransaction(fragment: Fragment){
            if(nowFragment == fragment){
                Toast.makeText(this, "이미 해당 Fragment를 보여주고 있습니다.", Toast.LENGTH_SHORT).show()
                return
            }
            transaction = fragmentManager.beginTransaction()
            transaction.replace(b.flFlagmentContainer.id, fragment).commitAllowingStateLoss()
            nowFragment = fragment
    
        }
    }
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        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=".MainActivity"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:orientation="horizontal">
            <View
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="0dp"/>
            <Button
                android:id="@+id/btn_present_main_fragment"
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:text="main"/>
            <Button
                android:id="@+id/btn_present_another_fragment"
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:text="another"/>
            <View
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="0dp"/>
        </LinearLayout>
        <FrameLayout
            android:id="@+id/fl_flagment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>

    MainHomeFragment

    더보기
    class MainHomeFragment : Fragment() {
    
        private var _binding: FragmentMainHomeBinding? = null
        private val binding get() = _binding!!
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            _binding = FragmentMainHomeBinding.inflate(inflater, container, false)
            return binding.root
        }
    
        override fun onDestroy() {
            super.onDestroy()
            _binding = null
        }
    }
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainHomeFragment"
        android:background="#FFEFEF">
    
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Home Flagment"
            android:textSize="40dp"
            android:textColor="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    MainAnotherFragment

    더보기
    class MainAnotherFragment : Fragment() {
    
        private var _binding: FragmentMainAnotherBinding? = null
        private val binding get() = _binding!!
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            _binding = FragmentMainAnotherBinding.inflate(inflater, container, false)
            return binding.root
        }
    
        override fun onDestroy() {
            super.onDestroy()
            _binding = null
        }
    
    }
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainAnotherFragment"
        android:background="#EFF2FF">
    
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Another Flagment"
            android:textSize="40dp"
            android:textColor="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

     

     

     

     

     

     

     

    반응형
    저작자표시 비영리 변경금지

    'IDE & Framework > Android' 카테고리의 다른 글

    [Kotlin] InCallService로 Default Dialer 개발하기  (4) 2021.12.19
    [Kotlin]ActivityForResult 및 checkSelfPerission 을 permissionLauncher로 대체하기  (0) 2021.12.19
    [Kotlin] Fragment (1) - Introduce  (0) 2021.12.12
    [Kotlin] WorkManager 사용해보기  (0) 2021.11.09
    [Kotiln] 실행아이콘이 없는, 런처가 없는 앱 만들기  (0) 2021.11.02
    • 개요
    • 구성
    • 결과
    'IDE & Framework/Android' 카테고리의 다른 글
    • [Kotlin] InCallService로 Default Dialer 개발하기
    • [Kotlin]ActivityForResult 및 checkSelfPerission 을 permissionLauncher로 대체하기
    • [Kotlin] Fragment (1) - Introduce
    • [Kotlin] WorkManager 사용해보기
    Greensky0026
    Greensky0026
    점이 모여 선이 된다. 내 삽질도 언젠간 거대한 지하 도시가 되겠지!

    티스토리툴바

    개인정보

    • 티스토리 홈
    • 포럼
    • 로그인

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.