Section 05
🎑 폰트 적용하는 법

res에font라는 새로운 디렉토리 만들기- 원하는 폰트의 .ttf 파일 or .otf 파일 font 폴더 안에 저장
- 적용을 원하는 TestView, Button, CheckBox 등에
android:fontFamily="@font/hanna_font"와 같이 불러서 적용
🎑 코틀린 리스트(Kotlin List)
- List란? 데이터를 순서대로 저장하는 Collection 중 하나
- index를 통해 각 요소에 접근할 수 있음
- List의 배열 순서는 0부터 시작
e.g. listOf("A", "B", "C") → 인덱스 0은 "A", 인덱스 1은 "B"

(로그로 리스트의 배열 상태를 확인한 사진)
// 1. List 생성 예시
val fruits = listOf("Apple", "Banana", "Cherry") // 읽기 전용 리스트
val colors = mutableListOf("Red", "Green") // 수정 가능한 리스트
// 2. 요소 접근
println(fruits[0]) // Apple
println(fruits[1]) // Banana
// 3. 요소 추가 (.add())
colors.add("Blue")
println(colors) // [Red, Green, Blue]
🎑 리스트뷰 구현
리스트뷰 작동 과정
![]() |
![]() |
|---|---|
| 순서 | 구성요소 | 역할 |
|---|---|---|
| 1 | MainActivity | 데이터 생성 및 어댑터 연결 |
| 2 | Adapter | 데이터 → 아이템 레이아웃에 바인딩 |
| 3 | Item (data class) | 리스트 한 칸의 데이터 형태 정의 |
| 4 | item_layout.xml | 각 아이템의 디자인 정의 |
| 5 | ListView | 화면에 모든 아이템을 나열하여 표시 |
어뎁터 생성 - ListViewAdapter.kt
어뎁터(Adapter) = 데이터를 View로 연결해주는 역할
ListViewAdapter이라는 새로운 코틀린 파일을 생성- 이 파일은 리스트의 각 항목을 화면에 어떻게 표시할지 정의하는 역할
- 파일 안에 다음과 같은 코드 작성
package com.example.week04
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
class ListViewAdapter(val List: MutableList
override fun getCount(): Int{
return List.size
}
override fun getItem(position: Int) : Any {
return List[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
var converView = convertView
if(converView == null){
converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent,false)
}
return converView!!
}}
**[코드 설명]**
- BaseAdapter: 리스트뷰를 커스터마이징할 수 있게 해주는 추상 클래스
- getCount(): 아이템 개수 반환
- getItem(): 특정 위치의 데이터 반환
- getView(): 각 아이템을 실제 뷰(View)로 만들어주는 함수
- convertView: 스크롤 시 이미 만들어진 뷰를 재사용해 성능 향상
<br/>
### activity_main.xml 레이아웃

<br/>
### MainActivity.kt
```kotlin
// 어뎁터에 데이터 넘겨주는 코드
val list_item = mutableListOf<String>()
list_item.add("a")
list_item.add("b")
list_item.add("c")
val listview = findViewById<ListView>(R.id.mainListview)
val listadapter = ListViewAdapter(list_item)
listview.adapter = listadapter [코드 설명]
- list_item: 실제로 표시할 데이터
- 어댑터(ListViewAdapter): 이 데이터를 기반으로 각 행의 View를 생성
- 리스트뷰에
.adapter로 연결해야 데이터가 화면에 표시
(결과물)
Adapter와 Item Layout 연결하기
- ListAdapter 다음과 같이 고치기 -> 리스트의 한 칸(아이템)에 들어갈 데이터를 실제 뷰에 적용
listview_item.xml안에 있는 TextVeiw를 찾아서(findViewById) 리스트의 문자열로 넣어줌 -> 데이터가 화면으로 바인딩됨
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
var converView = convertView
if(converView == null){
converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent,false)
}
val title = converView!!.findViewById<TextView>(R.id.listViewItem)
title.text = List[position]
return converView!!
}

ListViewModel 만들기
리스트에 단순 문자열만 넣는 대신, 하나의 아이템이 여러 정보를 가질 수 있도록 모델 클래스를 만들어줌
새로운 코틀린 파일 추가 ex) String을 2개 가지는 data class
package com.example.week04
data class ListViewModel (
var title: String = "",
var content: String = ""
)
모델을 사용하는 어뎁터 코드로 수정
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
var converView = convertView
if(converView == null){
converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent,false)
}
val title = converView!!.findViewById<TextView>(R.id.listViewItem1)
val content = converView!!.findViewById<TextView>(R.id.listViewItem2)
// List[0] -> ListViewModel("a","b")
title.text = List[position].title
content.text = List[position].content
return converView!!
}이렇게 코드를 수정하면 다음과 같이 모델을 리스트로 넘겨준 걸 볼 수 있음

🎑 더블클릭으로 종료하기
2초 안에 뒤로가기 버튼을 두 번 눌러야 앱이 종료되는 코드
API 33 이후로 안드로이드 스튜디오가 onBackPressed를 권장하지 않고 있기 때문에
다음과 같이 써야 함
private fun addOnBackPressedCallback() {
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// 뒤로 가기 버튼이 2번 눌렸을 때 처리 동작
if(isDouble == true){
finish()
return
}
// 한 번 클릭하면 변수 true
isDouble = true
Toast.makeText(this@MainActivity, "종료할거면 더블클릭", Toast.LENGTH_LONG).show()
// 2초 안에 다시 누르지 않으면 상태 초기화
android.os.Handler(Looper.getMainLooper()).postDelayed({
isDouble = false
}, 2000)
}
}
this.onBackPressedDispatcher.addCallback(this, callback)
}
[코드 설명]
| 단계 | 동작 | 설명 |
|---|---|---|
| ① | 사용자가 뒤로가기 버튼을 한 번 누름 | isDouble이 true로 바뀌고, 토스트 메시지 표시 |
| ② | 2초 안에 한 번 더 누름 | if (isDouble) 조건이 참이 되어 finish() 실행 → 앱 종료 |
| ③ | 2초가 지나면 | Handler가 isDouble = false로 초기화 (리셋) |
'TAVE-16th' 카테고리의 다른 글
| [TAVE 스터디 5주차] 메모 앱 만들기 (0) | 2026.01.04 |
|---|---|
| [TAVE 스터디 4주차] 음악 목록 앱 만들기 (0) | 2026.01.04 |
| [TAVE 스터디 3주차] 주사위 앱 만들기 (1) | 2026.01.04 |
| [TAVE 스터디 2주차] 사진앱 만들기(2) (0) | 2026.01.04 |
| [TAVE 스터디 1주차] 사진앱 만들기(1) (0) | 2026.01.04 |


