일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- sqlite
- 안드로이드
- forof문
- R데이터분석
- 이행은이미다른
- 자바스크립트날짜get
- 장고
- speechtoText
- 다른테이블에속해있습니다
- 장고프로젝트
- 자바스크립트forinforof차이
- Android
- 이행은이미다른테이블에속해있습니다
- 자바스크립트수학
- PostgreSQL
- 장고웹프로젝트
- 파이썬
- 자바스크립트for문
- 자바스크립트날짜
- 오류종류
- 개발
- speechAPI
- 자바스크립트날짜형식
- 청소년복지론
- Python
- webkitrecognition
- cmd명령어
- 사례관리
- 장고웹
- javaScriptError
- Today
- Total
EMDI는 지금도 개발중
Android with Kotlin : 안드로이드 기초편 - ListView 기초 프로세스 파악하기 본문
* ListsView : 같은 모양의 목록이 반복적으로 나타날 때 여러줄을 비슷한 모양, 자리에 맞는 데이터만 변경해서 출력
* ListView는 Data / ArrayList / Adapter 세 가지를 같이 사용
저번 시간까지는 Intent에 대해 배워보았습니다. 이번 시간부터는 ListView에 대해 공부해보도록 하겠습니다.
* 참고로 최근에는 ListView 대신 RecylerView를 많이 사용하는데 제가 학원에서 배운 부분은 ListView이기에 복습도 ListView로 우선 하도록 하겠습니다.
* 연습내용 : 직방 목록 사진과 같이 보증금, 월세, 주소, 층수, 설명에 대해 ListView를 만들어 보는 연습을 할 계획입니다. - 프로젝트명 : Review_ListView
순서 | 위치 | 프로세스 | |
1 | java > BaseActivity.kt 생성 | 공통적으로 사용하는 함수들을 미리 정의해두는 부분 - MainActivity처럼 자동생성하는 것이 아니고 우리가 직접 Kotlin Class로 생성 ▶ mContext, setupEvents(), setValues() 생성 ※ 역할 : 기본 틀 구성(기초작업) |
|
2 | java > MainActvity.kt | ▶ BaseActivity에서 생성한 setupEvents, setValues함수 override 하기 * 주의사항 : 꼭 TO-DO 주석 제거 및 onCreate함수에 setupEvents, setValues 넣기 ※ 역할 : 기본틀 만든 것과 연결(기초작업) |
|
3 | res > layout > activity_main.xml | 앱을 실행했을 때 화면에 바로 보여줄 부분 ▶ ListView 태그를 추가 및 id부여 ※ 역할 : 화면 리스트뷰 생성(디자인) |
|
4 | java > datas 패키지 생성 java > datas > Room.kt 생성 |
ListView가 뿌려줄 데이터들을 묶어서 표현하는 데이터 클래스 작업 ▶ 클래스의 생성자에서 val 변수이름 : 자료형 클래스가 가져야하는 정보 항목들로 설정 ※ 역할 : 데이터 항목 설정(DB) |
|
5 | res > layout > room_list_item.xml 생성 | ListView에 데이터가 뿌려질 모양을 xml로 설정 ▶ 한 줄에 해당하는 모양 설정 ※ 역할 : 한 줄씩 뿌려줄 때 보여줄 모습 생성(디자인) |
|
6 | java > adapters 패키지 생성 java > adapters > RoomAdapter 생성 |
데이터 클래스 객체들을 ArrayList에 담아서 Adapter에게 전달 하나하나의 객체들을 한 줄에 해당하는 XML과 연결해서 ListView에 뿌려주는 역할 ▶ Room 뿌려줄 데이터클래스 상속받고 필요한 데이터 순으로 텍스튜 변수에 담기 ※ 역할 : 매개체 생성 |
|
7 | java > MainActivity.kt | ▶ 액티비티에서 실제 목록을 담아줄 ArrayList만들고 실제 데이터 담아주기 DB와 관련된 데이터를 연결해줘야하는데 현재는 연습용이라 가라 데이터를 가지고 활용 ※ 역할 : 데이터 ArrayList에 담아놓기(소스) |
|
8 | java > MainActivity.kt | ▶ Adapter 클래스를 액티비티에 있는 리스트뷰와 연결 ※ 역할 : 매개체와 데이터 담아놓은 ArrayList 연결, 리스트뷰의 매개체인 것 지정 |
|
9 | java > adapters > RoomAdapter | ▶ 실제 데이터가 있는 목록이 반영되도록 하기 ※ 역할 : 리스트뷰의 텍스트뷰와 row 안에 있는 데이터와 연결하기 |
package com.mwsniper.review_listview
import androidx.appcompat.app.AppCompatActivity
abstract class BaseActivity : AppCompatActivity() {
// 어느 화면인지 알려줄 때 쓰는 용도의 변수 mContext 멤버변수로 지정
val mContext = this
// 이벤트 처리 코드를 모아두게 될 함수
abstract fun setupEvents()
// 화면에 데이터를 뿌리는데에 관련된 코드를 모아두게 될 함수
abstract fun setValues()
}
package com.mwsniper.review_listview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupEvents()
setValues()
}
override fun setupEvents() {
}
override fun setValues() {
}
}
1. BaseActivity 클래스 생성
자주 사용할 함수 와 mContext를 멤버변수로 잡고 MainActivity가 해당 클래스를 상속받도록 설정해줍니다
* BaseActivity는 AppCompatActivity()를 상속받고
* MainActvity는 BaseActivity()를 상속받도록 설정해줘야 합니다
2. MainActivity 클래스에 override 하기
BaseActivity에 2개의 추상메소드를 생성하였으니 상속받고 있는 MainActivity에도 해당 함수들을 상속받아야 합니다.
<!-- activity_main.xml -->
<?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"
android:orientation="vertical"
tools:context=".MainActivity">
//1. 액티비티 화면 (xml)에 리스트뷰 배치 + id 부여
<ListView
android:id="@+id/roomListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
3. activity_main.xml에 ListView태그 추가
실제 화면에서 보여줄 ListView태그를 추가합니다
* 참고로 디자인에서는 ListView의 모습이 보이지만 실제 앱을 실행했을 때는 ListView의 모습이 보이지 않습니다.
이와 같은 이유 : ListView는 Adapter의 도움을 받아서 내용목록을 출력하는데 아직 Adapter가 없어서 그렇습니다.
package com.mwsniper.review_listview.datas
// ListView가 뿌려줄 데이터들을 묶어서 표현하는 데이터 클래스 생성
class Room(
// 클래스의 생성자에서 변수들을 나열해서 클래스가 가져야하는 정보 항목들로 설정
val deposit: Int,
val monthlyRent: Int,
val address: String,
val floor: Int,
val description: String
) {
}
4. datas 패키지 생성 및 Room 데이터 클래스 생성
activity_main.xml에 있는 ListView에 뿌려줄 데이터들을 묶어서 표현하는 클래스. 생성자( val 변수명: 자료형 ) 이렇게 표현하며 우리는 앞서 보증금, 월세, 주소, 층수, 설명을 보여주기로 약속했으니 해당과 관련된 변수들을 생성하였습니다.
<!-- room_list_item.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgTxt"
android:layout_width="120dp"
android:layout_height="100dp"
android:src="@drawable/ic_launcher_foreground"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="15dp">
<TextView
android:id="@+id/priceTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="8,000(보증금) / 30(월세)"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/addressTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="주소, 1층"
android:textSize="16sp"
android:layout_marginTop="3dp"/>
<TextView
android:id="@+id/descTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="설명문구 쓰는 자리입니다."
android:layout_marginTop="3dp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
5. room_list_item.xml 추가
room_list_item.xml은 ListView의 List 하나마다 보여줄 모양을 설정하는 xml입니다. res > layout 에 Layout Resource File을 하나 추가해줍니다. 보통 ~_list_item.xml 이라고 이름을 짓습니다.
* 참고로 데이터들이 있는 LinearLayout 속성 중 gravity=center_vertical을 설정 안하면 글씨들이 제일 위에 설정이 되버립니다.
package com.mwsniper.review_listview.adapters
import android.content.Context
import android.content.LocusId
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import com.mwsniper.review_listview.R
import com.mwsniper.review_listview.datas.Room
// 2) 상속받은 뒤, Adapter 주 생성자에서 필요한 재료 받고
class RoomAdapter(
val mContext: Context,
val resId: Int,
val mList: List<Room>
// 1) ArrayAdapater<Room(뿌려줄 데이터클래스)>()를 상속받고
// 3) ArrayAdapter<Room>(mContext, resId, mList) 생성자에서 필요한 재료 순으로 부모에게 넘기기
) : ArrayAdapter<Room>(mContext, resId, mList) {
// 4) 객체로 변환해주는 변수를 멤버변수로 생성
val inf = LayoutInflater.from(mContext)
// 5) getView 오버라이딩
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
// 6) convertView 변수를 tempRow에 옮겨닮아서 null인경우 새로운 inflate해서 담기
// 이렇게 사용하는 이유는 listView를 재사용성하기 위해
var tempRow = convertView
if(tempRow == null) {
tempRow = inf.inflate(R.layout.room_list_item, null)
}
// tempRow는 맞지만 null은 절대 아니다 (= !!)
val row = tempRow!!
return row
}
}
6. adapters 패키지 및 adapter 생성
Adapter 클래스는 Data 클래스 + xml을 조합해서 ListView에 뿌리는 역할을 합니다. ArrayAdapter를 상속받는다고 명시를 하고 그 안에 뿌려줄 데이터클래스를 적용합니다.
* ArrayAdapter는 기본생성사 ()를 지원하지 않기때문에 만약 데이터 받는 재료를 적용안하고 넘어가면 오류가 뜹니다.
package com.mwsniper.review_listview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.mwsniper.review_listview.datas.Room
class MainActivity : BaseActivity() {
// 액티비테이서 실제 목록을 담아줄 ArrayList를 만들고 실제 데이터들을 담기
val mRoomList = ArrayList<Room>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupEvents()
setValues()
}
override fun setupEvents() {
}
override fun setValues() {
// 실제로 뿌려줄 데이터들 ArrayList변수에 추가
// 보증금, 월세, 주소, 층수, 설명
mRoomList.add(Room(8000, 30, "서울시 마포구", 1, "마포구 1층 방입니다."))
mRoomList.add(Room(10000, 50, "서울시 은평구", 10, "은평구 10층 방입니다."))
mRoomList.add(Room(3000, 80, "서울시 영등포구", 5, "영등포구 5층 방입니다."))
mRoomList.add(Room(5000, 15, "서울시 종로구", 4, "종로구 4층 방입니다."))
mRoomList.add(Room(9000, 20, "서울시 강서구", 8, "강서구 8층 방입니다."))
mRoomList.add(Room(12000, 40, "서울시 강북구", 17, "강북구 17층 방입니다."))
}
}
7. MainActivity에 ArrayList 만들기
액티비티에 실제 목록을 담아줄 ArrayList를 만들고 그 안에서 실제 데이터들을 담아줍니다. val 목록변수이름 = ArrayList<뿌려줄데이터클래스>() 실제로 뿌려줄 데이터들은 원래 서버에서 가져와야하지만 현재는 서버가 없으니 가라데이터를 만들어서 연습하였습니다.
package com.mwsniper.review_listview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.mwsniper.review_listview.adapters.RoomAdapter
import com.mwsniper.review_listview.datas.Room
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : BaseActivity() {
val mRoomList = ArrayList<Room>()
// 만들어둔 Adapter 클래스를 액티비티에 있는 리스트뷰와 연결
lateinit var mRoomAdapter: RoomAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupEvents()
setValues()
}
override fun setupEvents() {
}
override fun setValues() {
mRoomList.add(Room(8000, 30, "서울시 마포구", 1, "마포구 1층 방입니다."))
mRoomList.add(Room(10000, 50, "서울시 은평구", 10, "은평구 10층 방입니다."))
mRoomList.add(Room(3000, 80, "서울시 영등포구", 5, "영등포구 5층 방입니다."))
mRoomList.add(Room(5000, 15, "서울시 종로구", 4, "종로구 4층 방입니다."))
mRoomList.add(Room(9000, 20, "서울시 강서구", 8, "강서구 8층 방입니다."))
mRoomList.add(Room(12000, 40, "서울시 강북구", 17, "강북구 17층 방입니다."))
// Adapter 클래스를 객체화
// BaseActivity의 mContext, 어떤 리스트를 보여줄건지, 목록변수의 이름
// lateinit var로 초기화를 미뤘던 변수의 실제 초기화 코드
// (mContext=어떤화면에서?, romm_list_item=어떤모양으로그릴지?, mRoomList=어떤목록?)
mRoomAdapter = RoomAdapter(mContext, R.layout.room_list_item, mRoomList)
// 객체화된 adapter변수를 리스트뷰의 어댑터로 지정
// 실제 목록을 리스트뷰에 뿌려준다.
roomListView.adapter = mRoomAdapter
}
}
8. Adapter 클래스를 액티비티의 리스트뷰와 연결
RoomAdapter 클래스를 setValues에 만들었던 mRoomList와 연결하고 그것을 실제 화면에 보일 수 있도록 리스트뷰에 연결 시켜줍니다.
* 여기까지하면 리스트뷰에 아까 예시로 지정해둔 문구들이 줄줄이 생성되는 것을 확인할 수 있습니다.
* 참고로 실제 데이터들은 아직 반영되지 않은 상태
package com.mwsniper.review_listview.adapters
import android.content.Context
import android.content.LocusId
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.TextView
import com.mwsniper.review_listview.R
import com.mwsniper.review_listview.datas.Room
class RoomAdapter(
val mContext: Context,
val resId: Int,
val mList: List<Room>
) : ArrayAdapter<Room>(mContext, resId, mList) {
val inf = LayoutInflater.from(mContext)
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var tempRow = convertView
if(tempRow == null) {
tempRow = inf.inflate(R.layout.room_list_item, null)
}
val row = tempRow!!
// 실제 데이터가 있는 목록이 반영되도록 Adapter 클래스의 getView 함수를 수정
// 뿌려줄 row 안에 있는 텍스트 뷰 변수로 담기
val data = mList[position]
val price = row.findViewById<TextView>(R.id.priceTxt)
val address = row.findViewById<TextView>(R.id.addressTxt)
val desc = row.findViewById<TextView>(R.id.descTxt)
price.text = "${data.deposit} / ${data.monthlyRent}"
address.text = "${data.address}, ${data.floor}"
desc.text = data.description
return row
}
}
9. 리스트뷰의 id와 row안에있는 실제데이터 연결
마지막 작업으로 리스트뷰 안에 있는 TextView id와 row의 데이터를 연결하는 작업입니다. 해당 작업을 해야 실제 데이터가 리스트뷰에 출력됩니다. 여기까지 하셨으면 이미지를 제외한 나머지 TextView가 정상적으로 출력되는 것을 확인할 수 있을겁니다. 다음 글에서는 상세화면으로 넘어가서 디테일한 정보를 보여주는 연습을 해보도록 하겠습니다.
'네이티브 > Android' 카테고리의 다른 글
Android with Kotlin : 안드로이드 기초편 - ListView 기초 리스트뷰 클릭 시 상세화면 이동 (2) | 2020.09.21 |
---|---|
Android with Kotlin : 안드로이드 기초편 - Intent 활용 전화걸기, 문자발송, 인터넷연결 등 (0) | 2020.09.21 |
Android with Kotlin : 안드로이드 기초편 - Intent 활용 데이터 함께 화면전환 (0) | 2020.09.21 |
Android with Kotlin : 안드로이드 기초편 - Intent 기초 setOnClickListener 이벤트 (0) | 2020.09.21 |
Android with Kotlin : 안드로이드 기초편 - 회원가입 화면(UI) 만들기 (0) | 2020.09.21 |