
강사님께서 화면이 달라도 id는 최대한 다 다르게 설정하는것을 권장하셨다.
코루틴 특강 전에 쓰레드 강의 예정
모든 네트워크 테스트는 와이파이 끄고 lte로 바꾸고 중계기가 없는 실내(방 안)에서 테스트
데이터 용량을 최소화 시키는 것이 중요

내가 직접 만들었을 때는 체크박스 활성화를 위해 어떤 방법을 써야할지 able을 검색해서 나온 isClickable로 설정을했는데 강사님은 isEnabled로 설정하셨다. isClickable은 말그대로 클릭가능여부만 설정하는거라 시각적으로 비활성화 여부 확인이 어려웠는데 isEnabled=false로 비활성화를 시키면 시각적으로 회색으로 변경이되다보니 이게 훨씬 더 좋은 방법인 것 같다.
나는 onCreate 안에서 모든 코드를 넣었는데 강사님은 한번에 넣지 않고 화면 요소 초기화 함수와 이벤트 함수를 따로 만들어서 호출하는 방식으로 구현하셨다.
완성본

package kr.co.lion.ex06_view
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.ex06_view.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
initView()
setViewEvent()
}
// 화면 요소에 관련된 초기화
fun initView(){
// 취미 스위치는 on 상태로 설정한다.
activityMainBinding.apply {
switchHobby.isChecked = true
}
}
// 화면 요소에 대한 이벤트 설정
fun setViewEvent(){
activityMainBinding.apply {
// 취미 스위치 이벤트
switchHobby.setOnCheckedChangeListener { buttonView, isChecked ->
// on/off 상태로 분기한다.
when(isChecked){
// on상태라면...
true -> {
// 활성화
checkBoxHobby1.isEnabled = true
checkBoxHobby2.isEnabled = true
checkBoxHobby3.isEnabled = true
}
false -> {
// 비활성화
checkBoxHobby1.isEnabled = false
checkBoxHobby1.isChecked = false
checkBoxHobby2.isEnabled = false
checkBoxHobby2.isChecked = false
checkBoxHobby3.isEnabled = false
checkBoxHobby3.isChecked = false
}
}
}
// 버튼 이벤트
buttonSubmit.setOnClickListener {
// 아이디
textViewResult.text = "아이디 : ${textFieldUserId.text}\n"
// 비밀번호
textViewResult.append("비밀번호 : ${textFieldUserPw.text}\n")
// 사용자 이름
textViewResult.append("이름 : ${textFieldUserName.text}\n")
// 취미
// 스위치의 on/off 상태에 따라 분기
when(switchHobby.isChecked){
// off 상태면 취미가 없는 것으로 취급한다.
false -> textViewResult.append("선택한 취미는 없습니다.")
// on 상태면 체크박스에 체크한 것을 출력해준다.
true -> {
// 모든 체크박스가 체크되어 있지 않다면
if(checkBoxHobby1.isChecked == false
&& checkBoxHobby2.isChecked == false
&& checkBoxHobby3.isChecked == false){
textViewResult.append("선택한 취미는 없습니다.")
}else{
if(checkBoxHobby1.isChecked){
textViewResult.append("선택한 취미 : 축구\n")
}
if(checkBoxHobby2.isChecked){
textViewResult.append("선택한 취미 : 농구\n")
}
if(checkBoxHobby3.isChecked){
textViewResult.append("선택한 취미 : 야구\n")
}
}
}
}
}
}
}
}

보여질 항목의 전체 개수
어떤 데이터인지
어떤 모양으로 보여줄지
이 3가지를 어댑터를 통해 결정
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 이미지의 id
var imageRes = arrayOf(
R.drawable.imgflag1,
R.drawable.imgflag2,
R.drawable.imgflag3,
R.drawable.imgflag4,
R.drawable.imgflag5,
R.drawable.imgflag6,
R.drawable.imgflag7,
R.drawable.imgflag8
)
// 문자열1
val textData1 = arrayOf(
"토고", "프랑스", "스위스", "스페인", "일본", "독일", "브라질", "대한민국"
)
// 문자열2
val textData2 = arrayOf(
"탈락", "진출", "탈락", "진출", "탈락", "진출", "진출", "진출"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
}
}
inner class RecyclerViewAdapter{
}
inner class RecyclerViewAdapter{
ViewHolder
inner class ViewHolderClass(rowBinding: RowBinding) : RecyclerView.ViewHolder(rowBinding.root){
매개변수로 들어오는 바인딩객체를 담을 프로퍼티
var rowBinding:RowBinding
init{
this.rowBinding = rowBinding
}
}
}
class MainActivity : AppCompatActivity() {
...
inner class RecyclerViewAdapter : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolderClass>(){
//ViewHolder
inner class ViewHolderClass(rowBinding: RowBinding) : RecyclerView.ViewHolder(rowBinding.root){
// 매개변수로 들어오는 바인딩객체를 담을 프로퍼티
var rowBinding:RowBinding
init{
this.rowBinding = rowBinding
}
}
// ViewHolder 객체를 생성하여 반환한다.
// 새롭게 항목이 보여질 때 재사용 가능한 항목이 없다면 이 메서드를 호출한다.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderClass {
// View Binding
val rowBinding = RowBinding.inflate(layoutInflater)
// View Holder
val viewHolderClass = ViewHolderClass(rowBinding)
// 반환한다.
return viewHolderClass
}
// RecyclerView를 통해 보여줄 항목 전체의 개수를 반환한다.
override fun getItemCount(): Int {
return imageRes.size
}
// 항목의 View에 보여주고자 하는 데이터를 설정한다.
// 첫 번째 매개변수 : ViewHolder객체. 재사용 가능한 것이 없다면 onCreateViewHolder 메서드를 호출하고 반환하는 ViewHolder 객체가 들어오고
// 재사용 가능한 것이 있다면 재사용 가능한 ViewHolder객체가 들어온다.
// 두 번째 매개변수 : 구성하고자 하는 항목의 순서값(0부터 1씩 증가)
override fun onBindViewHolder(holder: ViewHolderClass, position: Int) {
holder.rowBinding.imageViewRow.setImageResource(imageRes[position])
holder.rowBinding.textViewRow1.text = textData1[position]
holder.rowBinding.textViewRow2.text = textData2[position]
}
}
...
}
MainActivity에서 어댑터 객체를 생성하여 적용해준다.
class MainActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
// 어댑터 객체 생성
val recyclerViewAdapter = RecyclerViewAdapter()
// 어댑터를 적용해준다.
recyclerView.adapter = recyclerViewAdapter
// RecyclerView의 항목을 보여줄 방식을 설정한다.
// 위에서 아래 방향
recyclerView.layoutManager = LinearLayoutManager(this@MainActivity) // 그냥 this는 activityMainBinding을 의미하게 되므로 MainActivity를 지칭할 수 있게 @를 붙여준다.
// RecyclerView Decoration
// 기본 구분선 넣기
// val deco = DividerItemDecoration(this@MainActivity, DividerItemDecoration.VERTICAL)
// recyclerView.addItemDecoration(deco)
// Material3 구분선 Divder 넣기 (구분선 범위를 직접 지정할 수 있음)
val deco = MaterialDividerItemDecoration(this@MainActivity, DividerItemDecoration.VERTICAL)
// 구분선 좌측 여백
// deco.dividerInsetStart = 450
// 구분선 우측 여백
// deco.dividerInsetEnd = 200
recyclerView.addItemDecoration(deco)
}
}
...
}

각 항목에 이벤트를 추가해줄 수 있다.
...
//ViewHolder
inner class ViewHolderClass(rowBinding: RowBinding) : RecyclerView.ViewHolder(rowBinding.root){
// 매개변수로 들어오는 바인딩객체를 담을 프로퍼티
var rowBinding:RowBinding
init{
this.rowBinding = rowBinding
// 현재 항목을 누르면 반응하는 리스너
// adapterPosition 프로퍼티 : 항목의 순서값
// 사용자가 터치한 항목이 몇 번째 항목인가로 사용한다.
this.rowBinding.root.setOnClickListener {
activityMainBinding.textView.text = "선택한 항목 : ${textData1[adapterPosition]}"
}
// View의 가로길이는 최대크기로 맞춰주어야 항목 옆의 공백을 눌러도 클릭이 된다.
// 직접 코드로 셋팅을 해줘야 한다.
this.rowBinding.root.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, // 가로길이
ViewGroup.LayoutParams.WRAP_CONTENT // 세로길이
)
}
}
...

리사이클러뷰의 갱신 방법
※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스