1. 뷰바인딩 사용설정
android {
...
viewBinding {
enable = true
}
}
2. 화면 설계
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/editTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="이름"
app:endIconMode="clear_text"
app:errorTextAppearance="@style/TextAppearance.AppCompat.Large">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/editTextAge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:endIconMode="clear_text"
app:errorTextAppearance="@style/TextAppearance.AppCompat.Large">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="나이"
android:inputType="number"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:gravity="center"
android:text="종류"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioButtonTypeDog"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_weight="1"
android:gravity="center"
android:text="강아지" />
<RadioButton
android:id="@+id/radioButtonTypeCat"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_weight="1"
android:gravity="center"
android:text="고양이" />
<RadioButton
android:id="@+id/radioButtonTypeParrot"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_weight="1"
android:gravity="center"
android:text="앵무새" />
</RadioGroup>
<TextView
android:id="@+id/gender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:gravity="center"
android:text="성별"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioButtonGenderMale"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:layout_weight="1"
android:gravity="center"
android:text="수컷" />
<RadioButton
android:id="@+id/radioButtonGenderFemale"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:layout_weight="1"
android:gravity="center"
android:text="암컷" />
</RadioGroup>
<TextView
android:id="@+id/gender2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:gravity="center"
android:text="좋아하는 간식"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkBoxAll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="간식전체"
app:checkedState="unchecked" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:orientation="vertical">
<CheckBox
android:id="@+id/checkBoxApple"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="사과" />
<CheckBox
android:id="@+id/checkBoxBanana"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="바나나" />
<CheckBox
android:id="@+id/checkBoxDaeChu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="대추" />
</LinearLayout>
<Button
android:id="@+id/buttonSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="저장" />
<Button
android:id="@+id/buttonPrint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="출력" />
<LinearLayout
android:id="@+id/animalContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
3. AnimalClass 설계
class AnimalClass(val name:String,val age:Int,val type:String,val gender:String,val snackList:MutableList<String>) {
}
4. Main_Activity 설계
import android.content.Context
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.google.android.material.checkbox.MaterialCheckBox
import com.lion.a017ex_animalmanager.databinding.ActivityMainBinding
import android.widget.CompoundButton.OnCheckedChangeListener
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
var animalList = mutableListOf<AnimalClass>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
activityMainBinding.apply {
//기본 체크값 세팅
radioButtonTypeDog.isChecked = true
radioButtonGenderMale.isChecked = true
checkBoxAll.isChecked = true
checkBoxApple.isChecked = true
checkBoxBanana.isChecked = true
checkBoxDaeChu.isChecked = true
buttonSave.setOnClickListener {
save()
resetInput()
}
buttonPrint.setOnClickListener {
print()
resetInput()
}
checkBoxAll.addOnCheckedStateChangedListener { checkBox, state ->
when (state) {
// 체크 상태일 때
MaterialCheckBox.STATE_CHECKED -> {
// 모든 체크박스를 체크한다.
checkBoxApple.isChecked = true
checkBoxBanana.isChecked = true
checkBoxDaeChu.isChecked = true
}
// 체크 상태가 아닐 때
MaterialCheckBox.STATE_UNCHECKED -> {
// 모든 체크스를 체크 해제한다.
checkBoxApple.isChecked = false
checkBoxBanana.isChecked = false
checkBoxDaeChu.isChecked = false
}
}
}
val checkBoxListener = OnCheckedChangeListener { buttonView, isChecked ->
// 체크되어 있는 체크박스의 개수를 담을 변수
var checkedCount = 0
// 체크박스들을 검사한다.
if (checkBoxApple.isChecked) {
checkedCount++
}
if (checkBoxBanana.isChecked) {
checkedCount++
}
if (checkBoxDaeChu.isChecked) {
checkedCount++
}
// 체크박스 개수에 따라 상태를 설정한다.
checkBoxAll.checkedState = if (checkedCount == 0) {
MaterialCheckBox.STATE_UNCHECKED
} else if (checkedCount == 3) {
MaterialCheckBox.STATE_CHECKED
} else {
MaterialCheckBox.STATE_INDETERMINATE
}
}
// 모든 체크박스에 설정한다
checkBoxApple.setOnCheckedChangeListener(checkBoxListener)
checkBoxBanana.setOnCheckedChangeListener(checkBoxListener)
checkBoxDaeChu.setOnCheckedChangeListener(checkBoxListener)
}
}
fun save() {
//저장할때 사용할 변수
var name: String?
var age: Int?
var type: String?
var gender: String?
var snackList = mutableListOf<String>()
name = activityMainBinding.editTextName.editText?.text.toString()
age = activityMainBinding.editTextAge.editText?.text.toString().toInt()
//동물종류에따라 분기하여 저장한다
if (activityMainBinding.radioButtonTypeDog.isChecked){
type = "강아지"
}else if(activityMainBinding.radioButtonTypeCat.isChecked){
type = "고양이"
}else {
type = "앵무새"
}
//동물성별에 따라 분기하여 저장한다
if (activityMainBinding.radioButtonGenderMale.isChecked){
gender = "수컷"
}else{
gender = "암컷"
}
//동물이 좋아하는 간식을 리스트에담는다
if (activityMainBinding.checkBoxApple.isChecked){
snackList.add("사과")
}
if (activityMainBinding.checkBoxBanana.isChecked){
snackList.add("바나나")
}
if (activityMainBinding.checkBoxDaeChu.isChecked){
snackList.add("대추")
}
//저장된 정보를 토대로 동물클래스를 생성한다
var animalClass = AnimalClass(name,age,type,gender,snackList)
//전체동물리스트에 객체를 추가한다
animalList.add(animalClass)
}
fun print() {
activityMainBinding.apply {
// 기존의 내용을 모두 지운다.
animalContainer.removeAllViews()
// animalList의 각 요소를 순회하며 출력
animalList.forEach { animal ->
// 동물 정보를 담을 TextView 생성
val animalInfo = TextView(this@MainActivity).apply {
text = """
이름: ${animal.name}
타입: ${animal.type}
나이: ${animal.age}
성별: ${animal.gender}
좋아하는 간식: ${animal.snackList.joinToString(", ")}
---------------------------
""".trimIndent()
textSize = 16f
}
// animalContainer에 추가
animalContainer.addView(animalInfo)
}
}
}
// 입력 요소 초기화
fun resetInput(){
activityMainBinding.apply {
// 각 입력 요소를 비워준다.
activityMainBinding.editTextName.editText?.setText("")
activityMainBinding.editTextAge.editText?.setText("")
// 첫 번째 입력 요소에 포커스를 준다.
activityMainBinding.editTextName.editText?.requestFocus()
// 키보드를 내린다.
val imm = activityMainBinding.root.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(activityMainBinding.root.windowToken, 0)
}
}
}
5. 동작영상
6. 출력부분에서 막힌부분
출력을 리스트뷰를 이용해서 쭉 출력하는 쉬운 방법이 있었지만 아직 부트캠프 진도상 리스트뷰를 배우지않아서 리스트뷰없이 출력하는법을 고민하다 동물리스트의 동물정보객체마다 스크롤뷰에 텍스트뷰를 추가하는방식을 사용했다
해당부분 코드는 다음과 같다
fun print() {
//동물 리스트가 비어있다면
if (animalList.size == 0){
activityMainBinding.apply {
// 기존의 내용을 모두 지운다.
animalContainer.removeAllViews()
val animalInfo = TextView(this@MainActivity).apply {
text = """
저장된 동물없음
---------------------------
""".trimIndent()
textSize = 16f
}
// animalContainer에 추가
animalContainer.addView(animalInfo)
}
}else{
activityMainBinding.apply {
// 기존의 내용을 모두 지운다.
animalContainer.removeAllViews()
// animalList의 각 요소를 순회하며 출력
animalList.forEach { animal ->
// 동물 정보를 담을 TextView 생성
val animalInfo = TextView(this@MainActivity).apply {
text = """
이름: ${animal.name}
타입: ${animal.type}
나이: ${animal.age}
성별: ${animal.gender}
좋아하는 간식: ${animal.snackList.joinToString(", ")}
---------------------------
""".trimIndent()
textSize = 16f
}
// animalContainer에 추가
animalContainer.addView(animalInfo)
}
}
}
}