Android androidx : 리사이클러 뷰 2

timothy jeong·2021년 11월 9일
0

Android with Kotlin

목록 보기
26/69

레이아웃 매니저

레이아웃 매니저는 어댑터로 만든 항목을 리사이클러 뷰에 배치한다. 레이아웃 매니저는 RecycelrView.LayoutManager 를 상속받은 클래스로, 라이브러리에서 다음의 기능을 제공한다.

  • LinearLayoutManager: 항목을 가로나 세로 방향으로 배치한다.
  • GridLayoutManager: 항목을 그리드로 배치한다.
  • StaggeredGridLayoutManager: 항목을 높이가 불규칙한 그리드로 배치한다.

LinearLayoutManager

보통 목록을 보여줄때 가로나 세로로 보여주기 때문에 LinearLayoutManager 를 가장 자주 사용한다.

항목 세로 배치

binding.recyclerView.layoutManager = LinearLayoutManager(this)

항목 가로 배치

val layoutManager = LinearLayoutManager(this)
        layoutManager.orientation = LinearLayoutManager.HORIZONTAL
        binding.recyclerView.layoutManager = layoutManager

GridLayoutManager

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 방향으로 리사이클링 항목을 생성할 수 있다.

StaggeredGridLayoutManager

그리드 레이아웃과 비슷하지만, 각 항목의 크기가 다르면 각자 크기가 다른 그리드가 생성된다.

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)
    }
}
  • onDraw : 항목이 배치되기 전에 호출된다, 매개변수로 전달되는 Canvas 객체로 각종 그림을 그릴 수가 있다. 이 함수에서 그린 그림 위에 항목이 나타난다.
 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)
    }
  • onDrawOver : 항목이 모두 배치된 두 호출된다. 이 함수의 매개변수로 전달되는 Canvas 객체로 그림을 그리며 항목 위에 이 그림이 나타난다.

아래는 리사이클러뷰 정중앙에 그림을 그리는 방법이다.

  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)
    }
  • getItemOffsets : 개별 항목을 꾸밀 때 호출된다. 매개변수로 전달되는 Rect 객체는 각 항목을 화면에 표시할때 필요한 사각형 정보이다. 이 사각형 정보를 이용해 네 방향의 여백을 설정할 수 있다. 또한 각 항목의 바탕색을 설정할 수도 있다.
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))
    }
}
profile
개발자

0개의 댓글