1.LayoutManager?
A LayoutManager is responsible for measuring and positioning item views within a RecyclerView as well as determining the policy for when to recycle item views that are no longer visible to the user. By changing the LayoutManager a RecyclerView can be used to implement a standard vertically scrolling list, a uniform grid, staggered grids, horizontally scrolling collections and more. Several stock layout managers are provided for general use.
Android Developer 사이트에서 확인할 수 있는 LayoutManager의 설명입니다.
간단히 설명을 드리면 RecyclerView에 그려지는 View의 크기 및 위치를 정하고, View 재활용을 담당하고 있습니다.
기본적으로 제공되고 있는 LayoutManager는 LinearLayoutManager
, GridLayoutManager
, StaggeredGridLayoutManager
가 있습니다.
2.LayoutManager Method
많은 함수들이 존재합니다. 이중에 오늘 CardStack View를 만들때 필요한 함수들에 대해서만 알아보겠습니다.
generateDefaultLayoutParams()
RecyclerView에 기본 LayoutPararm을 생성하는 작업을 합니다.
구현 코드
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
return RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State)
이 함수에서 실제 배치될 View를 그려주는 작업을 하게 됩니다.
먼저 이 함수에서는 파라미터 두 개를 받고 있는 것을 알 수 있습니다.recycler
, state
입니다.
recycler
RecyclerView에서 아주 중요한 역할을 하는 친구라는걸 이름에서 알 수 있습니다.
A Recycler is responsible for managing scrapped or detached item views for reuse.
scrapped 또는 detached된 View를 재사용하기 위해서 그 View들을 관리해주는 역할을 해준다고 합니다.
- scrapped : View가 RecyclerView에 붙어있지만 재사용 혹은 제거를 위해 마킹을 한 상태
- detached : View가 RecyclerView에서 detached된 상태
state
말 그대로 RecyclerView의 상태값입니다.
그리고 내부 컴포넌트끼리 데이터 통신을 위해서 사용되기도 한다고 합니다.
구현 코드
override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
detachAndScrapAttachedViews(recycler) // 1
if (itemCount < 1) return
val startPosition = (itemCount - 1).coerceAtMost(topPosition + preloadCount - 1)
for (position in startPosition downTo topPosition) {
val isTopView = position == topPosition
val drawPosition = position - topPosition
val view = recycler.getViewForPosition(position)
changeDefaultElevation(ViewCompat.getElevation(view))
if (isTopView) setTopViewOnTouchListener(view)
setElevation(
view,
if (isTopView) defaultElevation
else defaultElevation - 1f * drawPosition
)
measureChildWithMargins(view, 0, 0)
val params = view.layoutParams as RecyclerView.LayoutParams
layoutDecorated(
view,
params.leftMargin + paddingLeft,
params.topMargin + paddingTop,
getDecoratedMeasuredWidth(view) + params.leftMargin + paddingLeft,
getDecoratedMeasuredHeight(view) + params.topMargin + paddingTop
) // 2
if (drawPosition > 0) {
view.scaleX = validateScale(1 - scaleGap * drawPosition)
view.scaleY = validateScale(1 - scaleGap * drawPosition)
} else {
view.scaleX = validateScale(1f)
view.scaleY = validateScale(1f)
}
if (startXPosition == null || startYPosition == null) {
initStartPosition(view.x, view.y)
}
addView(view) // 3
}
}
1 : 현재 붙어있는 View들을 scrapped 상태로 변경해줍니다.
2 : view의 left, top, right, bottom 값을 정해줍니다.
3 : View를 실제로 붙여줍니다.
3.결과
LayoutManager를 이용하면 RecylcerView에서 다양하게 View를 표현 할 수 있습니다.
다음 포스트에선 이번 포스트에서 스리슬쩍 넘어간 Recycler에 대해서 더 알아보도록하겠습니다.
Github에서 전체 코드를 확인해보세요!
'dev > android' 카테고리의 다른 글
Dagger2 (feat. Android Developer, Codelab) (0) | 2020.01.04 |
---|---|
Playing with String and DataBinding in xml (0) | 2019.12.31 |