-
[Android Kotlin] 갤러리에서 이미지 가져와 RecyclerView에 적용하기개발 끄적끄적/Android 2020. 6. 3. 00:36반응형
안드로이드 개발을 하다 보면 내장 메모리에 접근할 경우가 꽤 있습니다. 앞서 포스팅한 RecyclerView와 permission 기능을 그대로 사용해보겠습니다.
먼저 갤러리에 접근하는 기능을 버튼에 넣어 화면에 띄워보겠습니다.
val REQUEST_GET_IMAGE = 105 ... get_image_btn.setOnClickListener { val intent = Intent(Intent.ACTION_PICK) intent.type = "image/*" startActivityForResult(intent, REQUEST_GET_IMAGE) }
startActivityForResult() 메소드는 startActivity()와 다르게 콜백 메소드를 부릅니다. 두번째 인자값 REQUEST_GET_IMAGE가 requestCode가 되고 onActivityResult()에서 받아온 data를 REQUEST_GET_IMAGE로 판별해 작업을 할 수 있습니다.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if(resultCode == Activity.RESULT_OK){ when(requestCode){ REQUEST_GET_IMAGE -> { try{ var uri = data?.data main_imgView.setImageURI(uri) }catch (e:Exception){} } } } }
실행해보겠습니다.
Permission을 허용해준 후, 갤러리에 접근해 이미지를 가져오는 기능은 잘 적용되네요. 이제 RecyclerView 내부의 버튼을 눌러 해당 view의 image를 변화시켜 보겠습니다.
RecyclerAdapter.kt
class RecyclerAdapter(val context: Context, val boardList: MutableList<DataClass>, val itemClick:(Int, DataClass) -> Unit): RecyclerView.Adapter<RecyclerAdapter.BaseViewHolder<*>>() { val TYPE_1 = 0 val TYPE_2 = 1 abstract class BaseViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) { abstract fun bind(item: T) } inner class ViewHolder1(itemView:View):BaseViewHolder<DataClass>(itemView){ val text = itemView.form_recycler_1_text val btn = itemView.form_recycler_1_btn val img = itemView.form_recycler_1_img override fun bind(item: DataClass) { text?.text = item.string if(item.image != ""){ img.setImageURI(Uri.parse(item.image)) } btn.setOnClickListener { itemClick(adapterPosition,item) } } } inner class ViewHolder2(itemView: View):BaseViewHolder<DataClass>(itemView){ val text = itemView.form_recycler_2_text val btn = itemView.form_recycler_2_btn val img = itemView.form_recycler_2_img override fun bind(item: DataClass) { text?.text = item.string if(item.image != ""){ img.setImageURI(Uri.parse(item.image)) } btn.setOnClickListener { itemClick(adapterPosition,item) } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*> { return when(viewType){ TYPE_1 -> { val view = LayoutInflater.from(context).inflate(R.layout.form_recyclerview_1, parent, false) ViewHolder1(view) } TYPE_2 -> { val view = LayoutInflater.from(context).inflate(R.layout.form_recyclerview_2, parent, false) ViewHolder2(view) } else -> throw IllegalArgumentException("Invalid view type") } } override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) { val element = boardList[position] when(holder){ is ViewHolder1 -> holder.bind(element as DataClass) is ViewHolder2 -> holder.bind(element as DataClass) else -> throw IllegalArgumentException() } } override fun getItemViewType(position: Int): Int { return boardList[position].type } override fun getItemCount(): Int { return boardList.size } }
- 임의로 DataClass의 image 기본값은 ""로 설정해뒀으니 image 값 판별
- ""가 아닐 때 setImageURI를 통해 이미지 데이터 바인딩
MainActivity.kt
class MainActivity : AppCompatActivity() { val TYPE_1 = 0 val TYPE_2 = 1 val PERMISSIONS_REQUEST_CODE = 100 var REQUIRED_PERMISSIONS = arrayOf<String>( Manifest.permission.READ_EXTERNAL_STORAGE) val REQUEST_GET_IMAGE = 105 var positionMain = 0 lateinit var itemMain:DataClass var dataList:MutableList<DataClass> = mutableListOf() lateinit var recyclerAdapter : RecyclerAdapter override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { when(requestCode){ PERMISSIONS_REQUEST_CODE -> { if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){ //권한 허용 }else{ //권한 거부됨 } return } } } private fun requestPermission(){ var permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) if(permissionCheck != PackageManager.PERMISSION_GRANTED){ //설명이 필요한지 if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)){ //설명 필요 (사용자가 요청을 거부한 적이 있음) ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSIONS_REQUEST_CODE ) }else{ //설명 필요하지 않음 ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSIONS_REQUEST_CODE ) } }else{ //권한 허용 } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if(resultCode == Activity.RESULT_OK){ when(requestCode){ REQUEST_GET_IMAGE -> { try{ var uri = data?.data dataList[positionMain].image = uri.toString() recyclerAdapter.notifyDataSetChanged() }catch (e:Exception){} } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) requestPermission() dataList.add(DataClass("", "1번타입_1", TYPE_1)) dataList.add(DataClass("", "1번타입_2", TYPE_1)) dataList.add(DataClass("","2번타입_1", TYPE_2)) dataList.add(DataClass("","2번타입_2", TYPE_2)) recyclerAdapter = RecyclerAdapter(this, dataList){ position, item -> positionMain = position itemMain = item val intent = Intent(Intent.ACTION_PICK) intent.type = "image/*" startActivityForResult(intent, REQUEST_GET_IMAGE) } main_recyclerVIew.adapter = recyclerAdapter main_recyclerVIew.layoutManager = LinearLayoutManager(this) } }
- RecyclerAdapter에서 반환된 itemClick의 인자인 position, item을 받음
- onActivityResult()에서 position값을 바탕으로 dataList의 image 값을 바꿈
- notifyDataSetChanged() 메소드를 이용해 recyclerAdapter내부의 값이 변화되었다고 알림
DataClass.kt
data class DataClass(var image:String, val string: String, val type:Int)
여기서 image 값을 var로 주어야 MainActivity에서 수정할 수 있습니다.
잘 적용됩니다. 여기서 주의할 점은 form_recyclerview_*의 image 설정인데요. scaleType을 "centerCrop"으로 주었더니 이미지를 꽉 채워 보여줍니다.
imageView의 scaleType 종류는 기회가 된다면 다음 포스팅 때 알아보겠습니다.
반응형'개발 끄적끄적 > Android' 카테고리의 다른 글
[Android Kotlin] Retrofit2 사용방법 - Interface와 Data Class까지 (1) 2020.06.04 [Android Kotlin] 카카오맵 사용하는 방법 (해시키 등록) + 내 위치 표시하기 (0) 2020.06.03 [Android Kotlin] Permission(권한) 얻기 (0) 2020.06.02 [Android Kotlin] RecyclerView Adapter View Type (리사이클러뷰 여러 뷰타입) (0) 2020.06.01 [Android Kotlin] Navigation Drawer를 이용한 사이드 메뉴 만들기 (0) 2020.06.01