1. 구현기능
-연락처 불러오기
-여러 뷰홀더를 이용하여 즐겨찾기 여부에 따라 다른 아이템뷰로 연락처 리스트 나타내기
-리사이클러뷰 어댑터를 리스트 어댑터 사용하기
-전화 걸기
2. 구현
1)Contact
data class Contact(val name:String, val num:String, val img: Bitmap?, val starred:Int)
-연락처 정보를 담는 데이터 클래스
2)CustomAdapter
class CustomAdapter() : ListAdapter<Contact,ViewHolder>(diffUtil){
interface ItemClick{
fun onClick(tel:String)
}
var itemClick : ItemClick? = null
override fun getItemViewType(position: Int): Int {
return currentList[position].starred
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when(viewType){
0 -> normalViewHolder(ItemNormalBinding.inflate(inflater,parent,false))
else -> likeViewHolder(ItemLikeBinding.inflate(inflater,parent,false))
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val contact:Contact = currentList[position]
if(holder is normalViewHolder){
holder.binding.root.setOnClickListener{
itemClick?.onClick(contact.num)
}
if(contact.img!=null){
holder.img.setImageBitmap(contact.img)
}
holder.num.text=contact.num
holder.name.text=contact.name
}else if(holder is likeViewHolder){
holder.binding.root.setOnClickListener{
itemClick?.onClick(contact.num)
}
if(contact.img!=null){
holder.img.setImageBitmap(contact.img)
}
holder.num.text=contact.num
holder.name.text=contact.name
}
}
companion object{
val diffUtil = object :DiffUtil.ItemCallback<Contact>(){
override fun areItemsTheSame(oldItem: Contact, newItem: Contact) = oldItem == newItem
override fun areContentsTheSame(oldItem: Contact, newItem: Contact) = oldItem == newItem
}
}
inner class normalViewHolder(val binding: ItemNormalBinding) : RecyclerView.ViewHolder(binding.root){
val img=binding.normalImg
val name=binding.normalName
val num=binding.normalNum
}
inner class likeViewHolder(val binding: ItemLikeBinding) : RecyclerView.ViewHolder(binding.root){
val img=binding.likeImg
val name=binding.likeName
val num= binding.likeNum
}
}
-diffUtil을 인자로 받아 아이템 비교에 관한 콜백 메소드를 작성
-즐겨찾기 여부에 따라 두가지의 뷰홀더 이너클래스 작성
-getItemViewType으로 뷰타입을 설정하는 함수 오버라이드
3)MainActivity
class MainActivity : AppCompatActivity() {
private val binding:ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
val adapter:CustomAdapter by lazy {
CustomAdapter()
}
val contacts = ArrayList<Contact>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
initRecyclerView()
getPermission()
}
fun getPermission(){
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
val permissions = arrayOf(android.Manifest.permission.READ_CONTACTS, android.Manifest.permission.CALL_PHONE)
var flag=false
for(i in permissions){
if(checkSelfPermission(i)==PackageManager.PERMISSION_DENIED){
flag=true
}
}
if(flag) requestPermissions(permissions,0)
else initContact()
}
fun initContact(){
if(checkSelfPermission(android.Manifest.permission.READ_CONTACTS)==PackageManager.PERMISSION_DENIED) return
contacts.clear()
val projection = arrayOf<String>(ContactsContract.CommonDataKinds.Phone.CONTACT_ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,ContactsContract.CommonDataKinds.Photo.PHOTO_URI, ContactsContract.Contacts.STARRED)
val cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,projection,null,null,null)
if(cursor==null) return
while (cursor.moveToNext()){
val nameidx=cursor.getColumnIndex(projection[1])
val numberidx=cursor.getColumnIndex(projection[2])
val photoidx=cursor.getColumnIndex(projection[3])
val starredidx=cursor.getColumnIndex(projection[4])
val name = cursor.getString(nameidx)
val number = cursor.getString(numberidx)
val photoUri = cursor.getString(photoidx)?.toUri()
println(photoUri)
val photo = photoUri?.let{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ImageDecoder.decodeBitmap(ImageDecoder.createSource(contentResolver, photoUri))
} else {
MediaStore.Images.Media.getBitmap(contentResolver, photoUri)
}
}
val starred = cursor.getInt(starredidx)
contacts+=Contact(name,number,photo,starred)
}
println("contacts:${contacts.size}")
adapter.submitList(contacts)
}
fun initRecyclerView(){
binding.recyclerView.apply{
layoutManager=LinearLayoutManager(this@MainActivity,LinearLayoutManager.VERTICAL,false)
this@MainActivity.adapter.itemClick = object : CustomAdapter.ItemClick{
override fun onClick(tel:String) {
startActivity(Intent("android.intent.action.CALL", Uri.parse("tel:"+tel.replace("-",""))))
}
}
this.adapter=this@MainActivity.adapter
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode == 0){
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
initContact()
}
}
}
}
-itemClick에 ItemClick을 오버라이드한 오브젝트를 할당하여 클릭시 전화가 가능하도록 함
-Cursor을 이용해 연락처 정보를 가져옴
-permission체크후 Contact정보를 가져오도록 함
'코틀린 개인 과제' 카테고리의 다른 글
이미지 검색앱 만들기 (0) | 2024.08.08 |
---|---|
뉴스 리더 앱 (0) | 2024.07.18 |
AppleMarket 구현 과제 (0) | 2024.07.15 |
회원가입 MVVM 과제 (0) | 2024.07.14 |
챌린지반 3주차 첫번째 과제: 디자인 패턴 구현 (0) | 2024.07.09 |