본문 바로가기
안드로이드 프로젝트/개발자 키우기 게임

[Kotlin] Fragment 동적 생성 후 잔디 형태 구현하기

by joh9911 2022. 9. 8.

 

 

예전에 이디야 앱을 따라 만들어 본 적이 있다.

 

내가 만든 메뉴 카테고리 페이지

 

TabLayout에는 4개의 Tab Item 있고, 이에 따라 4개의 Fragment를 만든 후, 뷰페이저로 처리를 해두었다.

각  Tab Item을 클릭 시, 또는 화면 슬라이드 시 해당 Fragment가 교체되게끔 작동한다.

 

 

 

 

 

앱을 다 만든 후 아차 싶었다.

"만약 메뉴 카테고리가 여러 개가 생기면 그때마다 Fragment를 추가해줘야 하나?"

설계를 잘못했다는 것을 깨달았고,  해결방법을 생각해보았다.

 

 

 

 

 

 

 

분명 서버에서 카테고리와 그에 따른 메뉴 정보들을 가져올 것이므로

해당 Activity에서 리스트로 정보들을 저장한 후, 카테고리 수 만큼 Fragment를 동적으로 생성하고

해당 Fragment에 메뉴 리스트를 넘겨주는 방식을 선택하기로 했었다.

 

 

 

 

 

 

만들려는 깃허브 잔디 모양 구조와 비슷해 보이기에 예전 기억을 되살려봤다..

 

 

 

<grass_page.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=".MainActivity">

    <TextView
        android:id="@+id/grass_page_top"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/dark_green"
        app:layout_constraintHeight_percent="0.1"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="0dp" />

    <TextView
        android:id="@+id/grass_page_money_value"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/white"
        android:fontFamily="@font/dung_guen_mo"
        android:gravity="right"
        android:text="0원"
        android:textColor="@color/black"
        android:textSize="25dp"
        app:layout_constraintBottom_toBottomOf="@+id/grass_page_top"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.04"
        app:layout_constraintHorizontal_bias="0.9"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent="0.5" />
    <ImageView
        android:id="@+id/grass_page_grass_image"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@mipmap/grass_icon"
        app:layout_constraintBottom_toTopOf="@+id/grass_page_topLine"
        app:layout_constraintEnd_toStartOf="@+id/text_linear"
        app:layout_constraintHorizontal_bias="0.1"
        app:layout_constraintStart_toStartOf="@+id/grass_page_top"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent="0.1" />
    <LinearLayout
        android:id="@+id/text_linear"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toTopOf="@+id/grass_page_topLine"
        app:layout_constraintEnd_toStartOf="@+id/grass_page_money_value"
        app:layout_constraintStart_toEndOf="@+id/grass_page_grass_image"
        app:layout_constraintTop_toTopOf="parent">
        <TextView
            android:id="@+id/grass_page_year_text"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="2022년"
            android:textColor="@color/black"
            android:gravity="center"
            android:autoSizeTextType="uniform"/>
        <TextView
            android:id="@+id/grass_page_month_text"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:text="1월"
            android:textColor="@color/black"
            android:gravity="center"
            android:layout_weight="1"
            android:autoSizeTextType="uniform"/>

    </LinearLayout>

    <TextView
        android:id="@+id/grass_page_topLine"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/black"
        app:layout_constraintTop_toBottomOf="@id/grass_page_top"
        />
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/grass_page_view_pager2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/dark_yellow"
        app:layout_constraintBottom_toTopOf="@+id/grass_page_bottom"
        app:layout_constraintHeight_percent="0.8"
        app:layout_constraintTop_toBottomOf="@+id/grass_page_top"
        tools:layout_editor_absoluteX="0dp" >
    </androidx.viewpager2.widget.ViewPager2>

    <TextView
        android:id="@+id/grass_page_view_pager2Line"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/black"
        app:layout_constraintTop_toBottomOf="@id/grass_page_view_pager2"
        />
    <TextView
        android:id="@+id/grass_page_bottom"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/bright_green"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHeight_percent="0.1"
        />


</androidx.constraintlayout.widget.ConstraintLayout>

 

 

grass_page.xml

 

 

 

 

Fragment가 띄울 xml 파일은 전에 다뤘던 <grass_page_view_pager_layout.xml> 이다.

 

 

[Kotlin] GridLayout에 동적으로 addView 해주기

저번 포스팅에는 총 3개 배열에 데이터를 나눠 저장했었다. // 해당 월의 날짜 정보 및 잔디 정보 var numberOfDateArray = ArrayList () var grassColorArray = ArrayList () var contributionCountArray = Array..

joh9911-programming-note.tistory.com

 

 

 

 

 

 

 

 

<GrassPageActivity.kt>

class GrassPageActivity: FragmentActivity() {
 
 fun divideGithubDataInfo(){
        for(index in 0 until githubData?.size!!){ // week 배열의 사이즈
            for (index1 in 0 until githubData?.get(index)?.contributionDays?.size!!){
                var date = githubData?.get(index)?.contributionDays?.get(index1)?.date.toString()
                var dateArray = date.split("-")
                if (index == 0 && index1 == 0){
                    githubDataArray.add(dateArray)
                }
                var tempMonth = dateArray[1]
                val monthInArray = githubDataArray[githubDataArray.size-1][1]
                if (tempMonth != monthInArray){
                    githubDataArray.add(dateArray)
                }
            }
        }
        val viewPager = findViewById<ViewPager2>(R.id.grass_page_view_pager2)
        val pagerAdapter = ScreenSlidePagerAdapter(this@GrassPageActivity)
        
        viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
        viewPager.adapter = pagerAdapter // 어댑터 연결
        
        viewPager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback(){
            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
                val yearText = findViewById<TextView>(R.id.grass_page_year_text)
                val monthText = findViewById<TextView>(R.id.grass_page_month_text)
                yearText.text = "${githubDataArray[position][0]}년"
                monthText.text = "${githubDataArray[position][1]}월"
            }
        })
    }

    inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {

        override fun getItemCount(): Int = githubDataArray.size

        override fun createFragment(position: Int): Fragment = GrassPageFragment(githubDataArray[position], githubData, playTime, position)
    }
 }

 

 

 

 

 

 

깃허브 정보를 나눠 저장하는 함수에 뷰페이저 관련 코드들을 추가하였다.

ScreenSlidePagerAdapter의 createFragment 매소드를 통해 Fragment를 동적으로 생성할 수 있다.

단순히 슬라이드 하여 페이지를 넘기면 생성되며,

이때 생성된 Fragment는 3개 이상의 Fragment가 추가로 생성될 때까지 유지된다. 

 

 

더보기

 

만약 position 0번 째의 Fragment가 생성되었다 할 때,

3개 이상 Fragment들이 생성되면, 초기 Fragment는 종료되었다가 

다시 position 0으로 위치하면 재생성된다.

 

 

 

 

 

 

배열 githubDataArray 에는 각각의 달 정보인 "2021 - 08 - 01", "2021 - 09 - 01", "2021 - 10 - 01" 형태로

총 size가 12 ~ 13가 될 것이며,

이는 getItemCount 매소드를 통해 총 생성 가능한 Fragment의 개수가 된다.

 

 

 

 

 

 

 

이제 만들고 싶은 Fragment의 인자로 전달하고 싶은 데이터를 넣어 보내주면 된다.

 

 

완성!

 

 

참고한 코드 입니다.

 

Slide between fragments using ViewPager2  |  Android Developers

Slide between fragments using ViewPager2 Notifications Save this page to your Developer Profile to get notifications on important updates. Stay organized with collections Save and categorize content based on your preferences. Screen slides are transitions

developer.android.com

 

댓글