Fragment, 한국어로 하면 조각 / 단편이라는 의미를 가지고 있습니다. 프래그먼트의 기능이 무엇이길래 이런 이름이 붙었을까요?
프래그먼트는 액티비티(activity)으로만 담을 수 없는 다양한 레이아웃들을 포함시킬때 사용되는 기능입니다. 한 Activity안에 넣을 수 있는 레이아웃에는 한계가 있습니다. 다음 페이지로 넘기지 않고, 같은 activity내에서 다양한 페이지들을 넣을 수 있는 기능입니다. 비유하자면 책 한권이 앱이라면, 그것을 묶어놓은 챕터는 Activity, 챕터 안에 들어가있는 페이지들을 Fragment라고 할 수 있습니다.
Fragment 예시 영상입니다.
만약 Activity로 위처럼 기믹을 작동시킨다면 최소한 5개 정도가 필요하지만, 위 영상은 Activity 하나와 Fragment 하나로만 작동이 됩니다. 비어 있는 Activity 위에 레이아웃인 Fragment를 얹어 작동이 된것입니다.
포토샵/ 일러스트로 따지면 Activity는 배경, Fragment는 위에 있는 레이어라고 보시면 됩니다.
같은 화면 안에 여러개의 단편적인 기능을 구사할 수 있는게 Fragment입니다.
그 다음은 Fragment 예제코드입니다.
우선 하기전에 strings.xml에 들어갈 코드입니다.
<!-- 질문1 -->
<string name="question1_title">프래그먼트1</string>
<string name="question1_1">Q1. 핳</string>
<string name="question1_1_answer1">헿</string>
<string name="question1_1_answer2">훃</string>
<string name="question1_2">Q2. 프래그먼트</string>
<string name="question1_2_answer1">예제</string>
<string name="question1_2_answer2">입니다</string>
<string name="question1_3">Q3. 놀라워라</string>
<string name="question1_3_answer1">아뇨</string>
<string name="question1_3_answer2">사실 놀랍지는 않습니다</string>
<!-- 질문2 --> <string name="question2_title">프래그먼트1-2</string>
<string name="question2_1">Q1. 스위치를해요</string>
<string name="question2_1_answer1">세상에</string>
<string name="question2_1_answer2">마상에</string>
<string name="question2_2">Q2. 소설도 쓰고</string>
<string name="question2_2_answer1">일도해서</string>
<string name="question2_2_answer2">맛이 조금 갔습니다</string>
<string name="question2_3">Q3. 하하</string>
<string name="question2_3_answer1">왜 인생은 바쁠까</string>
<string name="question2_3_answer2">바쁘니까 바쁩니다</string>
<!-- 질문3 --> <string name="question3_title">고액연봉</string>
<string name="question3_1">Q1. 을 받으면</string>
<string name="question3_1_answer1">매일매일 연어를 사먹을겁니다</string>
<string name="question3_1_answer2">연어 먹고 싶다</string>
<string name="question3_2">Q2. 축 처진 연인이 우울하다고 말했을 때 나는</string>
<string name="question3_2_answer1">왜 우울해? 뭐 때문에 우울한 거야?</string>
<string name="question3_2_answer2">초콜릿 머겅</string>
<string name="question3_3">Q3. 힘들게 이벤트를 준비한 나를 신나게 할 연인의 칭찬은?</string>
<string name="question3_3_answer1">고마워 요즘 바쁠 텐데 언제 이런 걸 생각했어?</string>
<string name="question3_3_answer2">라고 하고 싶은데 연인없습니다</string>
<!-- 질문4 --> <string name="question4_title">솔로란</string>
<string name="question4_1">Q1. 솔로부대</string>
<string name="question4_1_answer1">군단장</string>
<string name="question4_1_answer2">장교</string>
<string name="question4_2">Q2. 썸 중에 연인이 집에 놀러 온다고 했을 때 나는</string>
<string name="question4_2_answer1">쓰레기 버리기부터 화장실 청소까지 한다</string>
<string name="question4_2_answer2">집에 없다고 한다</string>
<string name="question4_3">Q3. 커플 해외여행 계획을 짜게 된 나는</string>
<string name="question4_3_answer1">하나 알 수 있는것은</string>
<string name="question4_3_answer2">백이면 백. 여행가면 깨집니다.</string>
</resources>
Main.Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btn_start = findViewById<Button>(R.id.button1)
btn_start.setOnClickListener{
val intent = Intent(this@MainActivity, TestActivity::class.java)
startActivity(intent)
}
}
}
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="319dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
TestActivity
class TestActivity : AppCompatActivity() {
private lateinit var viewPager: ViewPager2
val questionnaireResults = QuestionnaireResults()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
viewPager = findViewById(R.id.viewPager)
viewPager.adapter = ViewPagerAdapter(this)
viewPager.isUserInputEnabled = false
}
fun moveToNextQuestion() {
Log.d("jblee","viewPager.currentItem = ${viewPager.currentItem}")
if (viewPager.currentItem==3) {
Log.d("jblee","result = ${ArrayList(questionnaireResults.results)}")
val intent = Intent(this, MainActivity::class.java)
intent.putIntegerArrayListExtra("results", ArrayList(questionnaireResults.results))
startActivity(intent)
} else {
val nextItem = viewPager.currentItem + 1
if (nextItem < viewPager.adapter?.itemCount ?: 0) {
viewPager.setCurrentItem(nextItem, true)
}
}
}
}
class QuestionnaireResults {
val results = mutableListOf<Int>()
fun addResponses(responses: List<Int>) {
val mostFrequent = responses.groupingBy { it }.eachCount().maxByOrNull { it.value }?.key
mostFrequent?.let { results.add(it) }
}
}
activity_test.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=".TestActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ViewPagerAdapter는 우클릭 이후 new>file에 들어가셔서 ViewPagerAdapter.kt입력하셔서 새로 형성해야합니다.
ViewPagerAdapter
class ViewPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
override fun getItemCount(): Int {
return 4
}
override fun createFragment(position: Int): Fragment {
return QuestionFragment.newInstance(position)
}
}
프래그먼트는 따로 생성해야합니다.
우클릭하신 후에 new>fragment>blank를 클릭해주시면 프래그먼트가 형성이 됩니다.
QuestionFragment
class QuestionFragment : Fragment() {
private var questionType: Int = 0
private val questionTitles = listOf(
R.string.question1_title,
R.string.question2_title,
R.string.question3_title,
R.string.question4_title
)
private val questionTexts = listOf(
listOf(R.string.question1_1, R.string.question1_2, R.string.question1_3),
listOf(R.string.question2_1, R.string.question2_2, R.string.question2_3),
listOf(R.string.question3_1, R.string.question3_2, R.string.question3_3),
listOf(R.string.question4_1, R.string.question4_2, R.string.question4_3),
)
private val questionAnswers = listOf(
listOf(
listOf(R.string.question1_1_answer1, R.string.question1_1_answer2),
listOf(R.string.question1_2_answer1, R.string.question1_2_answer2),
listOf(R.string.question1_3_answer1, R.string.question1_3_answer2)
),
listOf(
listOf(R.string.question2_1_answer1, R.string.question2_1_answer2),
listOf(R.string.question2_2_answer1, R.string.question2_2_answer2),
listOf(R.string.question2_3_answer1, R.string.question2_3_answer2)
),
listOf(
listOf(R.string.question3_1_answer1, R.string.question3_1_answer2),
listOf(R.string.question3_2_answer1, R.string.question3_2_answer2),
listOf(R.string.question3_3_answer1, R.string.question3_3_answer2)
),
listOf(
listOf(R.string.question4_1_answer1, R.string.question4_1_answer2),
listOf(R.string.question4_2_answer1, R.string.question4_2_answer2),
listOf(R.string.question4_3_answer1, R.string.question4_3_answer2)
),
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
questionType = it.getInt(ARG_QUESTION_TYPE)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_question, container, false)
val title: TextView = view.findViewById(R.id.tv_question_title)
title.text = getString(questionTitles[questionType])
val questionTextViews = listOf<TextView>(
view.findViewById(R.id.tv_question_1),
view.findViewById(R.id.tv_question_2),
view.findViewById(R.id.tv_question_3)
)
val answerRadioGroups = listOf<RadioGroup>(
view.findViewById(R.id.rg_answer_1),
view.findViewById(R.id.rg_answer_2),
view.findViewById(R.id.rg_answer_3)
)
for (i in questionTextViews.indices) {
questionTextViews[i].text = getString(questionTexts[questionType][i])
val radioButton1 = answerRadioGroups[i].getChildAt(0) as RadioButton
val radioButton2 = answerRadioGroups[i].getChildAt(1) as RadioButton
radioButton1.text = getString(questionAnswers[questionType][i][0])
radioButton2.text = getString(questionAnswers[questionType][i][1])
}
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val answerRadioGroups = listOf<RadioGroup>(
view.findViewById(R.id.rg_answer_1),
view.findViewById(R.id.rg_answer_2),
view.findViewById(R.id.rg_answer_3)
)
val btnNext: Button = view.findViewById(R.id.btn_next)
btnNext.setOnClickListener {
//모든 질문에 대한 응답이 완료되었는지 확인
val isAllAnswered = answerRadioGroups.all { it.checkedRadioButtonId != -1 }
if (isAllAnswered) {
val responses = answerRadioGroups.map { radioGroup ->
val firstRadioButton = radioGroup.getChildAt(0) as RadioButton
if (firstRadioButton.isChecked) 1 else 2
}
(activity as? TestActivity)?.questionnaireResults?.addResponses(responses)
(activity as? TestActivity)?.moveToNextQuestion()
} else {
Toast.makeText(context, "모든 질문에 답해주세요.", Toast.LENGTH_SHORT).show()
}
}
if(questionType==3){
btnNext.setText("결과 확인")
}
}
companion object {
private const val ARG_QUESTION_TYPE = "questionType"
fun newInstance(questionType: Int): QuestionFragment {
val fragment = QuestionFragment()
val args = Bundle()
args.putInt(ARG_QUESTION_TYPE, questionType)
fragment.arguments = args
return fragment
}
}
}
fragment_question.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:padding="26dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="26dp"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/btn_next"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- 질문 타이틀 -->
<TextView
android:id="@+id/tv_question_title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:background="#F3F3BA"
android:layout_marginBottom="30dp"
android:text="@string/question1_title"
android:textSize="18sp"
android:textStyle="bold" />
<!-- 질문1 -->
<TextView
android:id="@+id/tv_question_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/question1_1"
android:textStyle="bold"
android:textSize="16sp" />
<RadioGroup
android:id="@+id/rg_answer_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/question1_1_answer1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/question1_1_answer2" />
</RadioGroup>
<!-- 질문2 -->
<TextView
android:id="@+id/tv_question_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:text="@string/question1_2"
android:textStyle="bold"
android:textSize="16sp" />
<RadioGroup
android:id="@+id/rg_answer_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/question1_2_answer1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/question1_2_answer2" />
</RadioGroup>
<!-- 질문3 -->
<TextView
android:id="@+id/tv_question_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:text="@string/question1_3"
android:textStyle="bold"
android:textSize="16sp" />
<RadioGroup
android:id="@+id/rg_answer_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/question1_3_answer1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/question1_3_answer2" />
</RadioGroup>
</LinearLayout>
<Button
android:id="@+id/btn_next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="다음"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
위에 코드 하시고 잘 안돌아가시면 alt + enter 누르시면 안드로이드 스튜디오가 조금 도와줍니다.
완전하지는 않아요. 보통 오류라고 해도 id문제이거나, 위에 순서대로 작성하셔서 그럴 가능성이 높습니다.
일단 전부 작성하신 다음에 뜨는 오류를 잡으시는게 가장 좋을거에요. ID 부재로 인해 오류가 많이 나오면 당황하지 마시고 그냥 적으세요.
그러면 좋은 하루 되세요!
'안드로이드 스튜디오' 카테고리의 다른 글
안드로이드 스튜디오 Intent(데이터 전송/액티비티 실행) (0) | 2024.03.20 |
---|---|
앱 기획안 작성 피그마 (피그마 기초 + 개인기록용 앱기획안) (5) | 2024.02.26 |
안드로이드 스튜디오 by lazy 코딩 (초기화버튼 만들기) (2) | 2024.01.31 |
안드로이드 스튜디오 로또앱 (0) | 2024.01.30 |
안드로이드 스튜디오 도형 만들기 (0) | 2024.01.26 |