Android

RecyclerView

onemask 2018. 12. 15. 21:21


/*

*  본 포스팅은 Udemy - Kotlin Android 부터 Firebase 서버 그리고 훌륭한 Chatbot 만들기를
   스스로 정리하고자 작성한 글입니다. 

/* 


Recycler View


your app needs to display a scrolling list of elements based on large data sets (or data that frequently changes), you should use RecyclerView as described on this page.


developer.android에 RecylerView를 찾으면 위와 같은 말을 찾을 수 있습니다. 

scrolling 되고 큰 데이터에 기준되거나 변화 될때, 너는 RecylerView를 사용해야한다. 



앱을 이용하다 보면 동일한 layout에 데이터만 바뀌어서 달라지는 화면을 볼 수 있습니다. 

RecyclerView반복되는 item_list를 데이터만 바꾸어 보여주게 합니다. 



[Goole Play_ 영화 Tab]




* 그래서 어떻게 ? 


맨 처음 Recycler View을 사용해 주기 위해서는 dependency 에서 해당 라이브러리를 설치해줘야합니다. 


   >   


[ app의 오른쪽 버튼 > open Module setting> dependency > + ]


누르고 appcompat 와 동일한 버전으로  설치합니다. 

위와 같은 방법외에도 기본 xml 디자인 창에서 다운 받는 방법도 있습니다. 





1.1 activity_main.xml 에 RecyclerView 만들기 

     activity_main에 반복적으로 나타 낼 화면을 RecyclerView로 설정합니다. 


1.2 list_item.xml 만들기.  

반복적으로 만들 list_item.xml 을 구성합니다. 


    

<1.1 Recycler Layout>                         <1.2 List Item >





여기서부터가 중요!

2.1 MainActivity 

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

    //layoutManger 설정.
var gridManager = GridLayoutManager(this,3)
recyclerview.layoutManager= gridManager

//recyclerview.layoutManager(GridLayoutManager(this,3) )



    //Adapter 설정.
recyclerview.adapter=MainRecyclerViewAdapter()
}

* RecylcerView를 위해 필요한 것 


1. layout manager
: layout manager를 통해 View 를 그려줘야 합니다. 

저는 GridLayoutManager로 화면 구성을 설정해주었습니다. 


2. RecylcerView는 Adapter

:  효율적으로 데이터와 뷰를 관리하기 위해 필요합니다.
  RecyclerView.ViewHolder를 상속받아 정의합니다.  

  View Holder 정의에 따라 UI가 표현됩니다. 또한 View Holder의 적용으로 View의 재사용이 가능합니다. 


class MainRecyclerViewAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

var images = arrayOf(R.drawable.back1,R.drawable.back2,R.drawable.back3,R.drawable.back4)
//2. 각각의 item 마다 데이터를 바인딩 .
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var view = holder as CustomViewHolder
view!!.imageView!!.setImageResource(images[position])

}
//1. 각각의 item 마다 디자인 레이아웃을 불러오기.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var view = LayoutInflater.from(parent!!.context).inflate(R.layout.item_recyclerlist,parent,false)
var params = view.layoutParams

if(viewType==0){
params.height = (parent.measuredWidth/3)*2
params.width=parent.measuredWidth
view.layoutParams=params
return CustomViewHolder(view)
}
else {
params.height=parent.measuredWidth/3
params.width=parent.measuredHeight/3
view.layoutParams=params
return CustomViewHolder(view)
}
}
// postion에 따라서 type을 바꿔주는 기능
override fun getItemViewType(position: Int): Int {
if(position==0)
return 0
else
return 1
//return 된 결과는 oncreateViewHolder viewType으로 넘어 간다.
}

// 슈퍼 클래스에 아무것도 생성이 안되었다고 에러가 발생한다. 슈퍼클래스는 상속해주는 부모 뷰를 말한다.
class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var imageView : ImageView? = null
init{
imageView=view!!.findViewById(R.id.imageview_list)
}

}
//3. item 의 개수를 카운트.
override fun getItemCount(): Int {
return 4
}
}

 * 기본적으로 RecyclerViewAdapter를 만들면 3가지 함수를 implement 합니다. 


1. onCreateViewHolder ( parent: ViewGroup,viewType: Int) : RecyclerView.VeiwHoldeer () {}

각각의 item 마다 디자인한 레이아웃을 불러옵니다.


2. onBindViewHolder(hoder: RecyclerView.ViewHodler,position:Int) {}

각각의 item 마다 데이터를 바인딩 해줍니다.


3. getItemCount() : Int{}     item의 개수를 카운트 해줍니다.


TMI)


 저 같은 경우는 인스타그램같이 한 이미지뷰를 그리드하게 나타내는 것이였기에 

 list item 에 들어갈 이미지들을 배열로 정의하고 

var images = arrayOf(R.drawable.back1,R.drawable.back2,R.drawable.back3,R.drawable.back4)


디자인한 레이아웃을 imageview로 해당 images의 position으로 접근했습니다.  

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var view = holder as CustomViewHolder
view!!.imageView!!.setImageResource(images[position])
}

위 코드에서 as란 코틀린 문법 중 스마트 캐스팅에 해당하는 말로

명시적인 타입 캐스팅을 사용합니다. 

즉 holder : RecyclerView.ViewHolder를 CustomViewHolder로 타입 캐스팅하는 것을 의미합니다. 


  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var view = LayoutInflater.from(parent!!.context).inflate(R.layout.item_recyclerlist,parent,false)
var params = view.layoutParams

if(viewType==0){
params.height = (parent.measuredWidth/3)*2
params.width=parent.measuredWidth
view.layoutParams=params
return CustomViewHolder(view)
}
else {
params.height=parent.measuredWidth/3
params.width=parent.measuredHeight/3
view.layoutParams=params
return CustomViewHolder(view)
}
}

위 함수에서 

LayoutInflater, params 라는 개념에 대한 정확한 이해가 필요하였는데, 

LayoutInflater란 XML에 정의된 Resource(자원) 들을 View의 형태로 반환해 줍니다. 

부모 뷰그룹에서 item_reyclerlist.xml을 view 형태로 반환하는 것을 의미하는 것입니다. 


cotext에 NullException관한 추가적 공부가 필요할 듯한데... 일단은 추후에 포스팅을 작성하겠습니다. 


if else 구문 에서는 

첫번째 온 Image에 대해서는 부모 Width의 높이만큼 높이는 (부모 너비 /3 *2 )만큼,  

나머지 image에 대해서는 부모 layout의 높이, 넓이의 1/3 처럼 정의됩니다. 


결과적으로 완성된 화면은 아래와 같습니다. 







LIST