안드로이드 스튜디오에서 시뮬레이션(Run) 시도 중 아래와 같은 에러를 발견했을 때 해결방법입니다.
【 ↓ 에러 내용 ↓】
2 issues were found when checking AAR metadata: 1. Dependency 'androidx.core:core-ktx:1.15.0' requires libraries and applications that depend on it to compile against version 35 or later of the Android APIs. :app is currently compiled against android-34. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.5.1 is 34. Recommended action: Update this project's version of the Android Gradle plugin to one that supports 35, then update this project to use compileSdk of at least 35.
Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on).
2. Dependency 'androidx.core:core:1.15.0' requires libraries and applications that depend on it to compile against version 35 or later of the Android APIs. :app is currently compiled against android-34. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.5.1 is 34.
Recommended action: Update this project's version of the Android Gradle plugin to one that supports 35, then update this project to use compileSdk of at least 35.
Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on).
분명 코드 부분에서는 문제가 없었으나, Gradle plugin 버전을 업데이트(상향) 하라는 내용인데, 결론은 현재 안드로이드 스튜디오에 설치된 SDK 34 버전을 SDK 35 버전으로 상향하면 해결되는 경우입니다. 안드로이드 스튜디오를 오래된 버전을 사용하고 있다면 공식사이트에서 최신 버전을 받아서 설치하면 되며(UI 같은 것도 조금 바뀌었습니다), 만약, 설치한 지 24년 3월 이후 설치했다면 즉, 거의 최근 버전이라면, 안드로이드 스튜디오를 새로 다운로드할 필요 없이, 안드로이드 스튜디오 메뉴에서 간단하게 해결할 수 있습니다.
1. File → Project Structure → Modules → Compile Sdk Version을 선택하고 API 35(최신 또는 원하는 버전)으로 적용한 후 안드로이드 스튜디오를 재실행해 주면 해결됩니다.
◈ ATtiny 85 칩과 PCB를 이용하여 크리스마스 선물용 LED 멜로디 키트를 DIY 해 보세요.
캐롤이나 동요, 혹은 자신이 좋아하는 곡의 멜로디를 코딩하여 키트로 출력할 수 있어요. 아래 이미지처럼 PCB로 제작해서 선물용에 어울리게끔 만들어 봤습니다. 크리스마스트리와 눈사람 두 가지 버전으로 만들었는데요, 하지만, 가정에서는 PCB를 직접 제작하기 쉽지 않죠, 그런데 JLC PCB 사이트 같은 곳을 이용한다면 적은 비용으로 쉽고 빠르게 이렇게 완성된 PCB기판을 받아 볼 수 있습니다.
1. 제작 준비하기
실습을 위해 아래와 같은 파일들을 준비해 보세요.
먼저, 아두이노 처럼 프로그래밍이 가능한 ATtiny85 IC가 필요합니다. 그리고 ATtiny85에 코드를 업로드하기 위한 아두이노 보드가 필요합니다.
8 pin IC 소켓은 tiny85 칩을 PCB에 바로 납땜해 버리게 되면 다른 곡을 다시 업로드할 수 없게 되므로 필요합니다. 콘덴서 부품은 Reset과 IC를 보호하기 위한 용도이므로 용량값에 구애받지 말고 가지고 있는 것을 사용하면 됩니다. 7805 IC는 5V이상의 입력 전원을 5V로 일정하게 출력해주는 정전압 IC로서 tiny85 칩을 보호하기 위한 용도로 사용됩니다. 그래서 작동 시간을 더 늘리기 위해, 배터리를 별도로 연결할 때, 더 유용하게 활용됩니다.
멜로디를 울려줄 스피커나 부저, 어떤것이든 가능한데요 소리의 떨림이 좀 있지만 크기가 작은 부저를 사용해도 되고, 크기가 조금 크지만 좀 더 좋은 소리를 낼 수 있는 스피커를 사용해도 됩니다.
당장 PCB기판이 없더라도 브레드 보드에 회로를 구성해서 실습해 볼 수 있도록 브레드보드를 준비하면 됩니다.
ATtiny85의 기본 사용법과 부트로더 올리는 영상은 아래 링크 게시글을 참고해 주세요.
【 중요 】 위의 게시물에도 추가 하였지만, ATtiny 보드 라이브러리만 설치해서 진행할 경우 tiny85 칩에 코딩해서 LED를 동작시키고 하는 것은 문제없으나, 멜로디 음 출력이 되지 않는 문제가 있어요. 그래서 이를 해결한 다른 보드 라이브러리(ATtiny core)를 추가로 설치해서 진행하면 해결할 수 있습니다.
다만, ATtiny core 라이브러리만 진행했을 경우에는 코딩까지는 문제 없으나 코딩한 대로 동작이 되지 않고 이상한 출력을 내며 제대로 동작되지 않는데요, 특히 부트로더가 올려지지 않은 새 칩을 코딩하면 이런 현상이 벌어지는데, 따라서 이를 해결하는 (코딩하는) 순서는 아래처럼 해야 합니다.
음계란 음악에 쓰이는 음을 높이의 차례대로 배열한 음의 층계를 말하는데요. "도, 레, 미, 파, 솔, 라, 시, 도" 의 8가지 음계를 옥타브라고 합니다.
각 음계의 이름을 계이름이라하며 세 가지 언어로 혼용해서 부르고 있습니다. 주로 악보에는 영문 음계로(코드) 표기합니다. 그런데 이런 음(소리)은 어떤 물질의 떨림(진동)에의해 만들어지는데요. 물질이 빠르게 진동한다면 높은 음이 나며, 느리게 진동한다면 낮은음을 발생시키게 되죠. 빠르게 진동하는 것을 주파수가 높다라고 하며, 느리게 진동하면 주파수가 낮다고 해요. 1초에 1회의 진동(떨림)을 주파수 1Hz로 부르며, 100떨리면 100Hz라고 말합니다.
낮은 도와 높은 도(한 옥타브)의 주파수(진동수)는 음 높이가 두 배 차이나며 (레~레, 미~미, 파~파... 마찬가지) 인간의 귀는 이 두 음을 높이는 다르지만 서로 같은 음으로 인식하게 되죠. 서로 다른 종류의 악기로 합주를 할 때 음이 일치가 되는 이유는 각각의 음 높이가 특정 주파수로 정리되었기에 가능한 것입니다.
가장 낮은 1옥타브 C(도)의 주파수는 32.7032Hz이며 그 위로 2옥타브 C의 주파수는 그 두 배인 65.4064Hz 임을 알 수 있죠, 샾(#) 음계는 반정도를 올린 음으로 이해하면 되며, 반음을 내릴 때는 플랫(♭) 기호를 사용합니다.
이제 이런 주파수를 참고해서 악보의 각 음계를 주파수 값으로 출력해내면 스피커의 떨림에 의해 악보대로 음악이 연주되는 것이죠. 그리고 아두이노 코드를 작성할 때는 소수점 이하를 반올림 한 값으로 사용하고, 이 주파수 값들을 pitches.h라는 헤더파일 형태로 정리해서 이용합니다.
그리고 음에는 음의 길이를 정해 줄 수 있는데요, 음의 길이에 따라 그림과 같은 음표로 구분해서 악보에 표시합니다.
그럼, 예시로 쉬운 동요 한 곡을 코드로 만드는 과정을 보여드릴게요.
먼저, 악보를 보고 계이름과 음의 길이를 다음 처럼 표시합니다.
이것을 Pitches.h 헤더파일을 참고해서 코드로 적으면 아래와 같습니다.
지금은 4옥타브 영역대를 메인 음역대로 했으나 만약 음정을 높이고 싶다면, C5, E5, G5... 이런 형태로 작성하면 됩니다.
이런 방법으로 어떤 곡이든 악보를 보고 코드화하여 멜로디를 출력할 수 있어요. 그리고 이번 프로젝트에서 각각의 음을 출력할 때마다 LED가 깜빡이도록 회로를 구성했어요.
기본적으로는 아두이노에 이런 형태로 연결해서 동작시킬 수 있지만.
누군가에게 선물할 수 있는 형태로 만들기위해 이번 프로젝트를 준비했습니다.
따라서 나노 보드 대신, 크기가 매우 작은 tiny85 칩을 사용했고, 배터리도 작은 리튬 배터리를 사용했으며, LED도 많이 넣어 볼거리가 좀 있도록 하였어요.
그리고 PCB로 제작할 때 장점은 보드 디자인을 원하는 모양으로 만들 수 있고, 선 연결을 직접 할 필요 없이 부품만 꽂고 땜하면 바로 완성되기 때문에 장점이 많습니다.
회로 설계는 이와 같이 했고요, 좀 더 화려하게 하고 싶다면, LED와 저항을 병렬로 더 추가해서 제작하면 됩니다.
3V의 CR2032배터리는 직렬로 연결하여 6V의 입력 전압을 만들어 주었고요, ATtiny85 칩의 동작전압은 2.7~5.5V인데 6V정도의 전압은 별문제는 없겠지만, 9V건전지 등 다른 전원을 사용할 때를 대비해서, 5V의 고정적인 출력으로 제어해 주는 7805 정전압 IC를 추가하였어요. (tiny85 IC보호)
2. 멜로디 회로 설계 및 PCB 보드 디자인하기
지금 보이는 이미지는 OrCAD라는 전자캐드 툴을 이용해서 회로를 디자인 하고 있는 이미지예요.
PCB(인쇄회로기판) 보드 설계는 먼저 1. 도면을 설계 작성하고 2. PCB보드 외형을 디자인하는 형태로 진행됩니다. 만약, CAD툴에서 기본적인 부품은 제공되지만, 없는 부품이 있다면 이렇게 만들어서 사용합니다.
도면 디자인에서는 각 부품 간 연결 정보만 있기 때문에, PCB디자인에서는 부품들의 실제 사이즈에 대한 정보가 필요합니다. 이것을 footprint 값이라고 하는데요.
이제 이정보들을 PCB Layout 툴로 넘겨서 부품의 배치와 패턴을 디자인해 줍니다.
패턴을 완성시킨 후 인쇄회로기판(PCB)을 출력하기 위한 각 층별 팬턴에 대한 필름을 생성하고, 그리고 부품을 삽입하기 위한 홀 드릴에 대한 정보 파일과 Tree 모양의 기판 형태를 제단 해주는 NC 데이터도 함께 만들어 주는데요, 이 파일들의 묶음을 거버(Gerber) 파일이라고 합니다.
프로젝트 탐색창에서 "Gradle Scripts" 항목을 펼쳐보면 "build.gradle.kts (Module :app)" 이 보이고 더블클릭해 열어서 아래 이미지처럼 viewBinding.isEnabled = true를 android { ... } 사이에 넣어주세요. 그리고 변경사항이 적용될 수 있도록 "Sync Now"를 클릭해 주세요.
Main Activity에는 아래처럼 기본 설정 코드가 들어 있을 텐데요,
이를 아래와 같이 필요 없는 항목은 지우고 ViewBinding을 사용하기 위한 형태로 바꾸어 주세요.
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
3. 전화번호 프로필(profile) 화면 구성하기.
프로필의 화면 구성은 아래와 같이 해볼게요.
프로젝트 탐색창에서 res 》 layout 에서 마우스 우클릭(이후로는 RMB로 표현)해서 New 》 Layout Resource File을 클릭하세요.
File name : 에 list_item이라 적고 OK를 클릭해 주세요.
그럼, 아래와 같이 layout 폴더에 list_item.xml이라는 파일이 생성된 것을 볼 수 있어요.
4. 액티비티 메인(activity_main.xml) 화면 구성하기.
추가한 ConstraintLayout이 클릭되어 있는 상태에서 오른쪽에 있는 Constraint Widget의 ⊕ 표시를 눌러 상위에 있는 부모 Constrait Layout과 연결을 시켜주세요.
그리고 아래 이미지처럼 각각의 마진(magin)을 8씩 주세요.
우선, 전화번호 목록에 쓰일 사람들의 사진을 대신하여 이미지 아이콘을 다운로드하여 사용해 볼 텐데요, flaticon.com에 접속하여 " profile " 로 검색해서 다운로드하여 볼게요.
검색된 아이콘들 중에 맘에 드는 것으로 몇 가지를 다운로드하여 보세요.
다운로드 표시 부분을 클릭하지 말고 이미지 가운데를 클릭하면, 가로 세로 원하는 사이즈를 선택해서 받을 수 있어요.
128픽셀을 선택해서 다운로드하세요. 512픽셀로 받아도 되지만, 기본크기가 너무 커지므로 줄여서 받아볼게요.
이 사이트의 경우 무료로는 하루 10개 정도 받을 수 있기 때문에 5개는 남자 이미지 5개는 여자 이미지로 총 10개를 다운로드하여서 아래와 같이 man1~5 , woman1~5로 네이밍 합니다.
그럼, 윈도 탐색창에서 위의 다운로드한 파일을 모두 선택해서 Ctrl + C(복사) 한 후, 안-스에서 프로젝트 탐색창의 res 》 drawable 폴더를 선택하고 Ctrl + V(붙여 넣기) 하세요.
그리고 OK 버튼을 클릭하면 아래처럼 해당 폴더에 붙여 넣기 됩니다.
물론 RMB 하여 Explorer 창을 열어 윈도 탐색창에 직업 붙여 넣기 해도 동일합니다. (해당 폴더를 바로 찾아 열어 볼 수 있음)
그리고 Attributes 속성 설정창에 보이는 Constrait Widget에서 화살표로 표시한 부분만 클릭해서 부모 Constraint Layout과 각각 연결시켜 주세요. 이때 연결되는 3곳 각각의 magin은 8 정도로 세팅할게요.
그리고 삽입한 man 이미지의 가로 폭(layout_width)과 세로 높이(layout_height)를 60dp로 설정해 주세요.
다음, Component Tree창에서 두 번째 ConstraintLayout을 선택하고 오른쪽 Constraints항목에 있는 부분에서 layout_height 만 wrap_content로 바꾸어 주세요.
다음, 제일 위에 있는 부모 ConstraintLayout을 선택해서 동일하게 layout_height를 wrap_content로 감싸주게 되면 아래 이미지처럼 이미지가 위쪽으로 정렬이 됩니다.
그다음, 이미지를 선택한 상태에서 id를 이미지 뷰를 줄인 약자(iv)로 해서 iv_profile로 설정해 볼게요.
id를 변경하고 엔터를 치면 , 아래와 같이 창이 나타나고 OK를 한 번 더 눌러주면 됩니다.
① 텍스트뷰를 끌어다 놓고, id = tv_name , text = 홍길동 입력하고, 아래처럼 Constraint Widget의 연결을 해주세요.
다음, text 속성에서 textSize = 16sp , textColor = #040404 , textStyle = Bold로 변경합니다.
② "전화번호"에 대한 TextView항목도 아래처럼 추가해 주세요.
Component Tree 창에서 tv_name을 Ctrl+C , Ctrl+V 하면 동일한 속성으로 복사가 됩니다.
그럼, id = tv_number로 바꾸고, 전화번호를 입력해 주세요. 색상도 적당한 색으로 바꾸고, Constraint Widget의 연결을 왼쪽 이름에 연결하고 정당한 magin을 입력해 주세요.
③ 동일한 방법으로 이메일에 대한 textView도 추가해서 아래처럼 적당할게 설정해 주세요.
④ 동일하게 생년월일에 대한 tv_birthday texView도 아래처럼 추가해 볼게요.
정리된 모습
5. list_item.xml에 대한 객체 모듈의 클래스 만들어주기
app 》 kotlin+java 》 com.example.recyclerview3 <RMB> 해서 New 》 Kotlin Class/File을 클릭하세요.
그리고 이름에 Profile이라고 입력하고 엔터 하면
Profile이라는 확장자가 KT인 코틀린 Class 파일이 생성된 것을 볼 수 있어요.
클래스 파일 내용은 아래와 같이 입력해서 "사진이미지, 이름, 전화번호, 이메일, 생일" 각각에 대한 인자와 받아들일 속성에 대해 정의해 주세요.
이때 이미지의 경우 숫자로 처리할 수 있기 때문에 Int형으로 정의합니다.
class Profile ( val picture : Int , val name : String , val telNum : String , val email : String , val birthDay : String )
6. 어댑터 만들기 (Adapter)
어댑터는 뷰 홀더에서 만든 뷰 객체에 적절한 데이터를 대입해서 항목을 완성하는 역할을 하는데요, 이어서 레이아웃 매니저가(LayoutManager) 어댑터가 만든 항목들을 어떻게 배치할지 결정하여 리사이클러 뷰에 출력합니다.
리사이클러뷰의 전체적인 구조는 아래와 같습니다.
이미지 출처 : s2choco.tistory.com이미지 출처 : recipes4dev.tistory.com
그럼, 뷰홀더를 만들 때처럼, app 》 kotlin+java》 com.example.recyclerview3 <RMB> 해서 New》 Kotlin Class/File을 클릭하세요. 파일 이름은 ProfileAdapter로 할게요.
클래스 파일이 생성되면 아래와 같이 우선 작성하고, 만약 RecyclerView 글자가 빨간색으로 뜬다면, 리사이클러 뷰 위젯을 자동으로 삽입되도록 Alt+Enter 하세요.
그리고 아래처럼 코드를 이어서 작성하면, class ProfileAdapter 부분이 붉은색 밑줄이 그어지는데 마우스를 올리고 나타나는 팝업창에서 Implement members를 클릭해서 필요한 구성요소들이 자동으로 생성될 수 있도록 해줍니다. 또는 Alt+Shift+Enter
이어서, CustomViewHolder 부분이 빨간 글자로 되는데, 이 부분도 마우스를 올리고 기다리고 있으면, 클래스를 자동으로 생성할 수 있도록 해줍니다.
그럼, 뷰홀더(View Holder) 클래스가 만들어지는데요,
아래와 같이 코드를 완성해 보세요. TODO 라고 되어 있는 부분들은 삭제하고,
list_item.xml에 있는 각각의 객체들을 findViewById로 변수명을 만들어 가져옵니다. getItemCount( ) 함수는 Main Activity에 입력되는 데이터의 총개수를 구해오는 함수입니다.
package com.example.recyclerview3
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class ProfileAdapter ( val profileList: ArrayList<Profile> ) : RecyclerView.Adapter<ProfileAdapter.CustomViewHolder> ( )
{
class CustomViewHolder (itemView: View) : RecyclerView.ViewHolder(itemView){ // : RecyclerView... 를 상속 받아 CustomViewHolder class를 작성함.
val picture = itemView.findViewById<ImageView>(R.id.iv_profile) // 인물 사진
val name = itemView.findViewById<TextView>(R.id.tv_name) // 이름
val telNum = itemView.findViewById<TextView>(R.id.tv_number) // 전화번호
val email = itemView.findViewById<TextView>(R.id.tv_email) // 이메일
val birthday = itemView.findViewById<TextView>(R.id.tv_birthday) // 생일
}
override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): ProfileAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) // parent에 있는 모든 정보(context)를 가져오는 설정 함.
return CustomViewHolder(view) // view 형태를 첨부 하여 위에서 정의한 CustomViewHolder( )를 리턴(호출) 함.
}
override fun onBindViewHolder(holder: ProfileAdapter.CustomViewHolder, position: Int) {
holder.picture.setImageResource(profileList.get(position).picture) // (MainActivity에서 데이터를 받아서) profileList에서 손으로 클릭(터치)되는 위치에 대한 정보를 가져옴.
holder.name.text = profileList.get(position).name // position 값은 데이터 0 부터 시작 됨.
holder.telNum.text = profileList.get(position).telNum // 만약 유형이 Int 숫자라면, 코드 마지막에 숫자를 문자열로 변환하는 코드를( '.toString()' ) 삽입해주면 에러나지 않음.
holder.email.text = profileList.get(position).email
holder.birthday.text = profileList.get(position).birthDay
}
override fun getItemCount(): Int {
return profileList.size // profileList의 총 데이터 갯수를 반환함.
}
}
7. 메인 레이아웃 구성하기 (activity_main.xml)
MainActivity.kt 파일을 열고서, 기본 주어지는 "HolloWorld!" textView를 지우고, 아래처럼, Common 》 RecyclerView를 끌어다 놓으세요.
그리고, Constrait Wideget의 4곳을 모두 클릭해서 parant에 모두 연결시켜 주세요.
리사이클러 뷰의 id는 rv_profile로 할게요.
8. 메인 액티비티 구성하기 (MainActivity.kt)
먼저, findViewById 대신 바인딩을 사용하기 위해, onCreate ( ) 함수 내에 바인딩 선언을 해주세요.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
그리고 profileList라는 변수를 만들고 arrayListOf ( )라는 리스트 함수를 사용하여 앞서 정의한 데이터들의 리스트를 담을 거예요.
이때 앞서 만든 Profile 클래스의 데이터 형식에 맞추어 입력해 주면 됩니다. 인물 Icon 이미지를 10개 준비했으니, 데이터도 우선 10개를 채워볼게요. class Profile ( 사진, 이름, 전화번호, 이메일, 생일 ) 형태로 작성해 주면 됩니다.
그리고 레이아웃매니저(layoutManager) 함수를 통해 어댑터가 만든 항목들을 어떻게 배치할지? (가로:HORIZONTAL, 세로:VERTICAL) 정해줍니다. 주로 위아래로 스크롤하는 형태가 되기 때문에, VERTICAL로 해주면 되고요. 이제 제일 중요한, 어댑터를 최초로 사용하게 되는데, ProfileAdapter( )를 가져와서 위에서 작성한 profileList를 담아 activity_main.xml 레이아웃의 id를 rv_profile이라고 이름 지은 RecyclerView로 바인딩하여 전달(보여주기) 해 주면 됩니다. 이 코드들은 아래와 같아요.
binding.rvProfile.layoutManager = LinearLayoutManager(this, LinearLayoutManager.H VERTICAL, false)
binding.rvProfile.setHasFixedSize(true) // 리사이클러뷰에 대한 성능개선 관련
binding.rvProfile.adapter = ProfileAdapter(profileList)
그럼, MainActivity.kt 파일의 완성된 전체 코드를 한 번에 보여드리면 아래와 같아요.
에뮬레이터에 뜬 화면을 마우스로 위아래 스크롤 해보면, 준비된 10개의 데이터가 스크롤되면서(VERTICAL) 잘 보이는 걸 알 수 있어요.
네, 대부분 잘 보이는데요, 몇몇 데이터가 Constrait (제약) 연결된 상태에 따라 이름의 길이가 짧거나 하여 이메일 주소와 생일이 겹치는 부분이 보이는데요, 데이터에 따라 크게 겹치지 않도록 Constrait Wedjet에 있는 항목들의 간격을 조정해 보세요. 생일의 TextView의 오른쪽이 전화번호의 오른쪽에 연결(연동) 시켜 놓았기 때문에 이름이 짧은 사람은 전화번호가 앞으로 당겨지게 되고 이로인하서 생일도 전화번호의 오른쪽라인으로 기준이 당겨지기 때문에 이메일과 겹치는 부분이 발생하였습니다.
따라서, 해결방법은 전화번호의 왼쪽이 연결된 이름과의 여백(magin)을 충분히 띄워 주면 됩니다.
또는 이름의 오른쪽과 연결시킨 부분을 사진의 왼쪽 부분으로 바꾸어 연결시키고 간격을 90sp로 적정하게 벌어지도록 하면, 이름의 길이에 따라 전화번호가 앞뒤는 움직이는 일은 없어서 깔끔하게 정렬된 출력을 볼 수 있어요.
이렇게 조정 후, 다시 실행시켜 보면, 깔끔하게 정렬된 것을 볼 수 있습니다.
9. 목록 클릭하여 정보 표시하기
해당 목록을 클릭하면 Toast기능을 사용하여 간단한 메시지를 출력해 보도록 할게요.
예를 들어, itemView 목록에서 엘사를 터치하면, 엘사의 "이름 [전화번호] , 이메일"을 짧은 메시지 형태로 보여주도록 할게요.
ProfileAdapter.kt 파일을 열고, onCreateViewHolder ( ) 함수 부분을 아래와 같이 수정(추가) 해 주세요.
override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): ProfileAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) // parent에 있는 모든 정보(context)를 가져오는 설정 함.
return CustomViewHolder(view).apply {
itemView.setOnClickListener {
val cursorPosition : Int = adapterPosition
val profile : Profile = profileList.get(cursorPosition)
Toast.makeText(parent.context, "-이름:${profile.name} [전화번호: ${profile.telNum}] \n-E메일: ${profile.email}", Toast.LENGTH_SHORT).show()
}
}
}
그리고 실행해서 터치해 보면, 해당하는 정보를 띄워주는 것을 볼 수 있습니다.
10. 목록 클릭하여 전화걸기
마지막으로, 해당 목록을 클릭하면 해당 연락처로 전화를 걸 수 있도록 해서 좀 더 효용성을 높여 봤습니다.
동일한 코드에 아랫부분만 수정해 보세요.
override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): ProfileAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) // parent에 있는 모든 정보(context)를 가져오는 설정 함.
return CustomViewHolder(view).apply {
itemView.setOnClickListener {
val cursorPosition : Int = adapterPosition
val profile : Profile = profileList.get(cursorPosition)
val intent = Intent(Intent.ACTION_DIAL)
intent.data = Uri.parse("tel:${profile.telNum}")
itemView.context.startActivity(intent)
}
}
}
앱을 실행시켜 보면, 서로 다른 항목을 클릭할 때마다 그 항목에 있는 전화번호로 전화 걸기가 잘 실행 되는 것을 볼 수 있네요.
※ 주의! 임의로 넣은 번호이지만 실제 해당 번호를 소유하고 있는 사람이 있을 수 있으므로, 실제 테스트하실 때는 가족이나 자신의 번호로 테스트해 보시길 바랍니다!