레이아웃 매니저는 어댑터로 만든 항목을 리사이클러 뷰에 배치한다. 레이아웃 매니저는 RecycelrView.LayoutManager 를 상속받은 클래스로, 라이브러리에서 다음의 기능을 제공한다.
보통 목록을 보여줄때 가로나 세로로 보여주기 때문에 LinearLayoutManager 를 가장 자주 사용한다.
항목 세로 배치
binding.recyclerView.layoutManager = LinearLayoutManager(this)
항목 가로 배치
val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
binding.recyclerView.layoutManager = layoutManager
val layoutManager = GridLayoutManager(this, 2)
binding.recyclerView.layoutManager = layoutManager
그리드 레이아웃 매니저를 만들때 두번째 인자는 열의 갯수를 의미한다. 가로방향부터 채우는게 디폴트이며, 세로방향부터 채우도록 만들고 싶으면 아래와 같이 한다.
val layoutManager = GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL, false)
binding.recyclerView.layoutManager = layoutManager
HORIZONTAL 인데 세로방향 부터 채우는게 잘 들어맞지 않는 것 같다. 네번쨰 인자 Boolean 값은 그리드가 시작하는 방향을 end 에서 start 로 할지 묻는 것으로 reverseLayout 이라고 한다. 이 값을 false 로 줌으로써 일반적인 start 에서 end 방향으로 리사이클링 항목을 생성할 수 있다.
그리드 레이아웃과 비슷하지만, 각 항목의 크기가 다르면 각자 크기가 다른 그리드가 생성된다.
val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL)
첫번쨰 인자는 spanCount로 두번째로 오는 orientation 값에 따라 의미가 달라지는데 만약 vertical 이면 열의 갯수가되고, 만약 horizontal 이면 행의 갯수가 된다.
아이템 데커레이션은 리사이클러 뷰를 다양하게 꾸밀 때 사용한다. 이는 필수 사항이 아니므로 필요한 경우에 출력하면 된다. 라이브러리에서 제공하는 아이템 데커레이션은 항목의 구분선을 출력해 주는 DividerItemDecoration 뿐이다. 더 다양하게 사용하기 위해서는 ItemDecoration 을 상속받는 개발자 클래스를 만들고 이 클래스에서 커스텀하게 꾸미기 작업을 해야한다.
커스텀 아이템 데커레이션을 만들어 보자.
class MyDecoration(val context: Context): RecyclerView.ItemDecoration() {
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
}
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDrawOver(c, parent, state)
}
override fun getItemOffsets(d
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
}
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
c.drawBitmap(BitmapFactory.decodeResource(context.resources, android.R.drawable.alert_light_frame),
0f,0f, null)
}
아래는 리사이클러뷰 정중앙에 그림을 그리는 방법이다.
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDrawOver(c, parent, state)
// 뷰 크기 확인
val width = parent.width
val height = parent.height
// 이미지 크기 계산
val dr: Drawable? = ResourcesCompat.getDrawable(context.resources,
android.R.drawable.btn_plus, null)
val drWidth = dr?.intrinsicWidth
val drHeight = dr?.intrinsicHeight
// 이미지가 그려질 위치 계산
val left = width / 2 - drWidth?.div(2) as Int
val top = height / 2 - drHeight?.div(2) as Int
c.drawBitmap(
BitmapFactory
.decodeResource(context.resources,
android.R.drawable.checkbox_on_background),
left.toFloat(),
top.toFloat(),
null)
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
// 뷰 어댑터의 onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) 함수에서 position
val idx = parent.getChildAdapterPosition(view) + 1
if (idx % 3 == 0)
outRect.set(10,10,10,60) // left, top, right, bottom
else
outRect.set(10,10,10, 0)
view.setBackgroundColor(Color.LTGRAY)
ViewCompat.setElevation(view, 20.0f)
}
이를 다시 액티비티 코드에서 리사이클러뷰 매니저에 적용하면 된다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = MyAdapter(datas)
binding.recyclerView.addItemDecoration(MyDecoration(this))
}
}