
내가 작성한 EX09 코드에서는 학생별 정보를 각각의 리스트로 담아서 정보를 각각 전달했는데
강사님의 경우 info클래스를 작성하여 객체를 전달하는 방식으로 작성하셨다.
점수 통계를 내는 과정도 내가 작성한 코드는 리스트를 통째로 전달해서 통계뷰에서 계산을 하고 보여주는 방식으로 작성했는데, 강사님의 경우 메인에서 먼저 계산을 한 후에 계산값을 통계뷰에 전달하여 출력하는 방식으로 작성하셨다.
강사님의 코드에서는 학생정보 입력 시 예외처리를 따로 안하셨는데 예외처리 하는 부분도 복습 겸 구현이 필요하다.
Parcelable 복습이 꼭 필요하다.
리사이클러뷰 항목의 position은 adapterPosition으로 찾을 수 있음
studentList[adapterPosition] 이런식으로
// 항목을 터치했을 때의 이벤트
this.rowMainBinding.root.setOnClickListener {
// ShowInfoActivity를 실행한다.
val newIntent = Intent(this@MainActivity, ShowInfoActivity::class.java)
// 선택한 항목 번째의 객체를 Intent에 담아준다.
newIntent.putExtra("obj", studentList[adapterPosition])
showInfoActivityLauncher.launch(newIntent)
}
리사이클러뷰 항목을 클릭할 때 애니메이션 효과 부여

레이아웃의 배경속성을 selectableItemBackground로 설정하면 된다.
android:background="?android:attr/selectableItemBackground"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="10dp">
// InfoClass.kt
class InfoClass(var name: String?, var grade:Int, var kor:Int, var eng:Int, var math:Int) : Parcelable {
}
// InfoClass.kt
package kr.co.lion.ex09_activity
import android.os.Parcel
import android.os.Parcelable
class InfoClass(var name: String?, var grade:Int, var kor:Int, var eng:Int, var math:Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt(),
parcel.readInt(),
parcel.readInt(),
parcel.readInt()
) {
}
// 객체를 다른 실행단위로 보낼때 호출되는 메서드
// 안드로이드 OS에서 첫 번째 매개변수로 parcel 객체가 전달된다.
// 이 객체는 다른 실행 단위로 전달되는 객체이다.
// parcel 객체는 객체가 가지고 있는 프로퍼티의 값을 저장해준다.
// 이 값은 다른 실행단위로 전달된다.
// 이 메서드는 putExtra 메서드를 호출할 때 호출된다.
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(name)
parcel.writeInt(grade)
parcel.writeInt(kor)
parcel.writeInt(eng)
parcel.writeInt(math)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<InfoClass> {
// 이 메서드는 parcel을 전달받은 새로운 실행단위에서 호출되는 메서드
// 이 메서에서는 사용하고자 하는 객체를 생성한다.
// 매개 변수에는 parcel 객체가 전달된다.
// parcel 객체에 저장되어 있는 값들을 추출하여 새롭게 생성한 객체의
// 프로퍼티에 저장해주는 작업을 한다.
override fun createFromParcel(parcel: Parcel): InfoClass {
return InfoClass(parcel)
}
override fun newArray(size: Int): Array<InfoClass?> {
return arrayOfNulls(size)
}
}
}
// MainActivity.kt
...
// 초기 데이터 셋팅
fun initData(){
// InputActivity 등록
val contract1 = ActivityResultContracts.StartActivityForResult()
inputActivityLauncher = registerForActivityResult(contract1){
if(it.resultCode == RESULT_OK){
if(it.data != null){
// 객체를 추출한다.
// createFromParcel 메서드가 호출되고 반환하는 객체를 반환해준다.
val info1 = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
it.data!!.getParcelableExtra("obj", InfoClass::class.java)
} else {
it.data!!.getParcelableExtra<InfoClass>("obj")
}
// Log.d("test1234", "${info1?.name}")
// Log.d("test1234", "${info1?.grade}")
// Log.d("test1234", "${info1?.kor}")
// Log.d("test1234", "${info1?.eng}")
// Log.d("test1234", "${info1?.math}")
// 리스트에 객체를 담는다.
studentList.add(info1!!)
// 리사이클러 뷰를 갱신한다.
activityMainBinding.recyclerViewItem.adapter?.notifyDataSetChanged()
}
}
}
...
}
...
홈버튼, 타이틀, 메뉴버튼 3개로 구성되어있음



Menu Item을 Menu에 배치할 때 ComponentTree가 아니라 미리보기 화면에 드래그를 하는 것을 권장함
ComponentTree에 드래그하여 배치할 경우 코드상으로 layout_width와 layout_height가 자동생성됨 -> MenuItem에는 필요없는 속성임


id : 각 메뉴를 구분하기 위한 이름
title : 메뉴에 표시되는 문자열
showAsAction : 메뉴 항목을 툴바에 배치할 것인지를 설정한다.
always : 항상 툴바에 배치한다.

아이콘이 있을 경우

아이콘이 없을 경우
ifRoom : 공간이 허락할 경우 툴바에 배치한다.

never : 툴바에 배치하지 않는다.

withText : 아이콘이 설정되어 있을 경우 아이콘이 보여지고 공간이 허락되면 title에 설정된 문자열도 보인다.


package kr.co.lion.android27_toolbar
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android27_toolbar.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
toolbar.apply {
// 타이틀
title = "툴바 입니다"
// 타이틀 문자열 색상
setTitleTextColor(Color.WHITE)
// res/menu/main_menu.xml 파일을 이용해 툴바의 메뉴를 생성한다.
// id : 각 메뉴를 구분하기 위한 이름
// title : 메뉴에 표시되는 문자열
// showAsAction : 메뉴 항목을 툴바에 배치할 것인지를 설정한다.
// always : 항상 툴바에 배치한다.
// ifRoom : 공간이 허락할 경우 툴바에 배치한다.
// never : 툴바에 배치하지 않는다.
// withText : 아이콘이 설정되어 있을 경우 아이콘이 보여지고 공간이 허락되면 title에 설정된 문자열도 보인다.
// collapseActionView는 사용하지 않음
inflateMenu(R.menu.main_menu)
// 메뉴를 선택하면 동작하는 리스너
// 매개변수에는 사용자가 선택한 메뉴 항목의 객체가 전달된다.
setOnMenuItemClickListener {
// 선택한 메뉴의 id로 분기한다.
when(it.itemId){
R.id.menuItem1 -> textView.text = "메뉴 1을 선택했습니다."
R.id.menuItem2 -> textView.text = "메뉴 2를 선택했습니다."
R.id.menuItem31 -> textView.text = "메뉴 3-1을 선택했습니다."
R.id.menuItem32 -> textView.text = "메뉴 3-2를 선택했습니다."
}
true
}
}
}
}
}

// SecondActivity.kt
package kr.co.lion.android27_toolbar
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android27_toolbar.databinding.ActivityMainBinding
import kr.co.lion.android27_toolbar.databinding.ActivitySecondBinding
class SecondActivity : AppCompatActivity() {
lateinit var activitySecondBinding: ActivitySecondBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activitySecondBinding = ActivitySecondBinding.inflate(layoutInflater)
setContentView(activitySecondBinding.root)
activitySecondBinding.apply {
toolbarSecond.apply {
title = "SecondActivity"
// 좌측 상단의 홈 버튼 아이콘을 설정한다.
setNavigationIcon(R.drawable.arrow_back_24px)
}
}
}
}
※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스