
추후 과제는 깃허브를 이용하여 제출할 예정임
구현 순서
툴바에 사용할 아이콘 drawable폴더에 붙여넣기
메인 ui구현(layout > activity_main.xml)
메인 ui에서 사용할 툴바 ui 구현(menu > menu_main.xml)
메인액티비티에서 툴바구현함수 작성 후 onCreate에서 호출
리사이클러뷰 항목으로 사용할 레이아웃 구현(layout > row_main.xml)
메인액티비티에서 리사이클러뷰 어댑터 클래스 작성 후 어댑터 설정하는 함수를 onCreate에서 호출
학생정보입력을 위한 액티비티 추가(InputActivity, activity_input.xml)
입력 ui구현(layout > activity_input.xml)
(textField의 inputType을 text로 직접 설정하지 않으면 multiline 입력이 가능하게됨)
입력 ui에서 사용할 툴바 ui 구현(menu > menu_input.xml)
입력액티비티에서 툴바구현함수 작성 후 onCreate에서 호출
메인액티비티에서 입력액티비티 런처 구현(inputActivityLauncher)
메인액티비티에서 툴바 메뉴 클릭 시 입력액티비티로 이동 구현
학생정보출력을 위한 액티비티 추가(ShowInfoActivity, activity_show_info.xml)
메인액티비티에서 학생정보출력액티비티 런처 구현(showInfoActivityLauncher)
메인액티비티의 리사이클러뷰 어댑터에서 항목을 누르면 학생정보출력액티비티 런처를 실행하도록 구현(showInfoActivityLauncher.launch(showInfoIntent))
학생정보출력 ui 구현
학생정보출력 ui에서 사용할 툴바 ui 구현(메뉴아이템이 없으면 메뉴xml파일은 따로 만들지 않음)
학생정보출력액티비티에서 툴바구현함수 작성 후 onCreate에서 호출
학생정보입력화면으로 이동할때
맨처음 입력칸에 포커스를 주고 키보드를 올려주도록 셋팅해야 함
// View 설정
fun setView(){
activityInputBinding.apply {
// 뷰에 포커스를 준다.
textFieldInputName.requestFocus()
// 키보드를 올린다.
// 이때 View를 지정해줘야 한다.
val inputmethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
inputmethodManager.showSoftInput(textFieldInputName, 0)
}
}
setView함수를 onCreate()에서 호출을 해버리면 키보드가 올라오지 않음
onCreate가 끝나야 화면이 다 만들어지고 키보드를 올리는 명령을 내릴 수 있기 때문
이때 thread를 사용하면 됨
// View 설정
fun setView(){
activityInputBinding.apply {
// 뷰에 포커스를 준다.
// 키보드를 올린다.
// 이때 View를 지정해줘야 한다.
showSoftInput(textFieldInputName)
}
}
// 포커스를 주고 키보드를 올려주는 메서드
fun showSoftInput(focusView:TextInputEditText){
focusView.requestFocus()
thread {
SystemClock.sleep(300)
val inputmethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
inputmethodManager.showSoftInput(focusView, 0)
}
}
안드로이드 에뮬레이터가 느릴경우 sleep시간을 300ms 미만으로 해버리면 키보드가 안올라오는 것으로 확인
학생정보입력액티비티에서 툴바의 완료 아이콘을 누르면 호출할 입력완료처리함수 작성
마지막 수학점수를 입력하고 엔터키를 누르면 입력완료처리함수 호출
학생정보입력액티비티에서 입력누락 시 보여줄 다이얼로그를 메서드로 작성해서 입력완료처리함수에서 호출
// 다이얼로그를 보여주는 메서드
fun showDialog(title:String, message:String, focusView:TextInputEditText){
// 다이얼로그를 보여준다.
val builder = MaterialAlertDialogBuilder(this@InputActivity).apply {
setTitle(title)
setMessage(message)
setPositiveButton("확인"){ dialogInterface: DialogInterface, i: Int ->
focusView.setText("")
focusView.requestFocus()
showSoftInput(focusView)
}
}
builder.show()
}
// 입력 완료 처리
fun processInputDone(){
// Toast.makeText(this@InputActivity,"눌러졌습니다",Toast.LENGTH_SHORT).show()
activityInputBinding.apply {
// 사용자가 입력한 내용을 가져온다
val name = textFieldInputName.text.toString()
val gradeStr = textFieldInputGrade.text.toString()
val korStr = textFieldInputKor.text.toString()
val engStr = textFieldInputEng.text.toString()
val mathStr = textFieldInputMath.text.toString()
// 입력 검사
if(name.length == 0){
showDialog("이름 입력 오류", "이름을 입력해주세요", textFieldInputName)
return
}
// 이전으로 돌아간다.
setResult(RESULT_OK)
finish()
}
}
각 화면별로 구현할 기능 확인
학생정보 클래스 파일 만들기(StudentData.kt)
StudentData클래스는 Parcelable 인터페이스를 구현함
생성자 구현 시 parcel.readString()이 null을 허용하기 때문에 기본생성자에 name 매개변수를 허용하는 것으로 설정해줌


메인액티비티에서 학생객체를 담을 리스트 생성하고 리사이클러뷰어댑터의 onBindViewHolder에 항목에 넣을 텍스트값 설정
입력액티비티에서 입력받은 정보를 학생 객체에 담아주고 Intent객체 생성해서 넣어준다음에 이전으로 돌아갈때 전달한다.
// 입력받은 정보를 객체에 담아 준다.
val studentData = StudentData(name, gradeStr.toInt(), korStr.toInt(), engStr.toInt(), mathStr.toInt())
Snackbar.make(activityInputBinding.root, "등록이 완료되었습니다", Snackbar.LENGTH_SHORT).show()
// 이전으로 돌아간다.
val resultIntent = Intent()
resultIntent.putExtra("studentData",studentData)
setResult(RESULT_OK, resultIntent)
finish()
입력 액티비티에서 전달받은 학생 객체를 추출해서 학생리스트에 담고 리사이클러뷰를 갱신한다.
// InputActivity 런처
val contract1 = ActivityResultContracts.StartActivityForResult()
inputActivityLauncher = registerForActivityResult(contract1){
// 작업 결과가 OK라면
if(it.resultCode == RESULT_OK){
// 전달된 Intent객체가 있다면
if(it.data != null){
// 학생 객체를 추출한다.
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU){
val studentData = it.data?.getParcelableExtra("studentData", StudentData::class.java)
studentList.add(studentData!!)
activityMainBinding.recyclerViewMain.adapter?.notifyDataSetChanged()
}else{
val studentData = it.data?.getParcelableExtra<StudentData>("studentData")
}
}
}
} // 갔다가 돌아올때 실행할 콜백 함수
메인 액티비티에서 리사이클러뷰 항목을 눌렀을 때 해당 항목의 학생 객체를 Intent에 담아서 학생정보출력 액티비티를 실행할 때 전달해준다.
// 항목을 눌렀을 때의 리스너
this.rowMainBinding.root.setOnClickListener {
// ShowInfoActivity를 실행한다.
val showInfoIntent = Intent(this@MainActivity, ShowInfoActivity::class.java)
// 선택한 항목 번째의 학생 객체를 Intent에 담아준다.
showInfoIntent.putExtra("studentData", studentList[adapterPosition])
showInfoActivityLauncher.launch(showInfoIntent)
}
학생정보출력 액티비티에서 Intent로 전달받은 학생 정보 객체를 추출하여 텍스트 뷰에 출력
// 뷰 설정
fun setView(){
activityShowInfoBinding.apply {
// TextView
textViewShowInfoReport.apply {
// Intent로 부터 학생 정보 객체를 추출한다.
val studentData = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
intent.getParcelableExtra("studentData", StudentData::class.java)
}else{
intent.getParcelableExtra<StudentData>("studentData")
}
text = "이름 : ${studentData?.name}\n"
append("학년 : ${studentData?.grade}학년\n")
append("\n")
append("국어 점수 : ${studentData?.kor}점\n")
append("영어 점수 : ${studentData?.eng}점\n")
append("수학 점수 : ${studentData?.math}점\n")
append("\n")
val total = studentData!!.kor + studentData!!.eng + studentData!!.math
append("총점 : ${total}점\n")
append("평균 : ${total / 3}점")
}
}
}
리사이클러뷰 항목 삭제 기능을 위한 컨텍스트메뉴 ui 구현(menu > menu_main_row.xml)
메인 액티비티의 ViewHolder클래스의 init블럭에 컨택스트 메뉴 기능 구현
// ViewHolder
inner class ViewHolderMain(rowMainBinding: RowMainBinding):RecyclerView.ViewHolder(rowMainBinding.root){
var rowMainBinding:RowMainBinding
init {
this.rowMainBinding = rowMainBinding
// 항목을 길게 눌렀을 때 메뉴를 띄운다.
this.rowMainBinding.root.setOnCreateContextMenuListener { menu, v, menuInfo ->
// 메뉴를 구성한다.
menuInflater.inflate(R.menu.menu_main_row, menu)
// 메뉴 항목을 눌렀을 때
menu?.findItem(R.id.menu_main_row_item_delete)?.setOnMenuItemClickListener {
// adapterPosition 번째 객체를 리스트에서 제거한다.
studentList.removeAt(adapterPosition)
// RecyclerView를 갱신한다.
activityMainBinding.recyclerViewMain.adapter?.notifyDataSetChanged()
true
}
}
}
※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스