
안드로이드에서 사용자 맞춤형 UI를 구현할 때 커스텀 뷰를 사용하는 것이 매우 유용합니다.
이번 포스팅에서는 GameListView라는 커스텀 뷰를 만들어, XML에서 속성만으로 쉽게 조정할 수 있는 방법을 소개합니다. 이 뷰는 게임 목록을 RecyclerView로 보여주며, 카드 유형과 레이아웃을 속성에 따라 유연하게 조정할 수 있습니다.
1. 커스텀 뷰 만들기
GameListView라는 커스텀 뷰는 LinearLayout을 확장하여 구현했습니다.
이 뷰는 게임 데이터를 리스트 형식으로 보여주며, RecyclerView를 통해 레이아웃을 구성합니다. 특히, 이 커스텀 뷰는 XML에서 속성을 정의하여 다양한 레이아웃을 설정할 수 있습니다. 즉, 뷰를 XML에 선언만 하면, 해당 속성을 이용해 간편하게 사용할 수 있습니다.
class GameListView @JvmOverloads constructor(
context: Context,
attr: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0
) : LinearLayout(context, attr, defStyleAttr) {
// View 속성 및 설정 코드...
}
주요 구현
- GameListView는 LinearLayout을 상속받으며, RecyclerView를 통해 데이터를 리스트 형식으로 보여줍니다.
- attrs.xml에서 속성을 받아와 레이아웃 옵션을 설정합니다. 카드의 유형에 따라 GridLayoutManager 또는 LinearLayoutManager를 적용할 수 있습니다.
- submitList 함수는 외부에서 데이터를 전달받아 RecyclerView의 어댑터에 설정합니다.
2. attrs.xml에 속성 정의하기
GameListView에서 사용할 수 있는 다양한 속성들은 attrs.xml에 정의되어 있습니다. 이 속성을 통해 레이아웃을 더욱 유연하게 구성할 수 있습니다.
attrs.xml 설명
attrs.xml은 커스텀 뷰의 속성을 정의하는 파일입니다. 커스텀 뷰를 구현할 때 attrs.xml에 속성을 정의하면 XML 레이아웃 파일에서 뷰의 동작과 외형을 쉽게 제어할 수 있습니다. 이번 GameListView의 경우, 카드 유형, 이미지 크기, 타이틀 표시 여부 등 다양한 옵션을 제공하기 위해 속성을 정의했습니다.
<resources>
<declare-styleable name="GameListView">
<!-- 카드의 타입을 정의하는 속성 -->
<attr name="cardType" format="enum">
<enum name="big_promo_image" value="0" /> <!-- 큰 프로모 이미지 -->
<enum name="list" value="1" /> <!-- 리스트 카드 -->
<enum name="small_image" value="2" /> <!-- 작은 이미지 카드 -->
<enum name="big_featured_image" value="3" /><!-- 큰 이미지 카드 -->
</attr>
<!-- 리스트 카드에서 사용할 spanCount (열 개수)를 정의하는 속성 -->
<attr name="spanCount" format="integer" />
<!-- 이미지 크기를 정의하는 속성 -->
<attr name="imageViewSize" format="enum">
<enum name="small" value="1" /> <!-- 작은 이미지 크기 -->
<enum name="big" value="2" /> <!-- 큰 이미지 크기 -->
</attr>
<!-- 카테고리 타이틀의 가시성을 정의하는 속성 -->
<attr name="categoryTitleVisibility" format="enum">
<enum name="visible" value="1" /> <!-- 타이틀 표시 -->
<enum name="gone" value="2" /> <!-- 타이틀 숨김 -->
</attr>
</declare-styleable>
</resources>
주요 속성 설명
- cardType: 이 속성은 보여줄 카드의 유형을 정의합니다. 예를 들어, big_promo_image는 큰 프로모션 이미지를 보여주고, list는 리스트 형태의 카드를 나타냅니다.
- spanCount: GridLayoutManager를 사용할 때 열의 개수를 정의하는 속성입니다. 기본적으로 리스트 카드는 여러 열로 구성될 수 있으며, 이 속성으로 열의 개수를 설정할 수 있습니다.
- imageViewSize: 카드에 보여줄 이미지의 크기를 정의하는 속성입니다. 작은 이미지와 큰 이미지 두 가지 옵션을 제공하며, 이를 통해 다양한 카드 레이아웃을 만들 수 있습니다.
- categoryTitleVisibility: 타이틀의 가시성을 설정하는 속성입니다. 타이틀을 표시할지, 숨길지를 설정할 수 있어 더 유연한 레이아웃 구성이 가능합니다.
속성 적용 방식: obtainStyledAttributes
이제 이 속성들이 어떻게 커스텀 뷰에서 인식되어 적용되는지 설명하겠습니다. 커스텀 뷰는 obtainStyledAttributes() 메서드를 사용하여 XML에서 정의된 속성을 가져옵니다.
context.theme.obtainStyledAttributes(attr, R.styleable.GameListView, 0, 0).apply {
try {
// XML에서 cardType 속성 값을 가져와 적용
cardType = getInt(R.styleable.GameListView_cardType, 0)
spanCount = getInt(R.styleable.GameListView_spanCount, 3)
sizeType = getInt(R.styleable.GameListView_imageViewSize, ImageSizeConstants.SIZE_SMALL)
titleVisibility = getInt(R.styleable.GameListView_categoryTitleVisibility, View.GONE)
} finally {
recycle() // 메모리 관리를 위해 recycle() 호출
}
}
obtainStyledAttributes 설명:
- obtainStyledAttributes()는 XML에서 정의된 속성을 TypedArray 객체로 가져옵니다.
- 이 메서드를 통해 XML에서 정의한 속성 값을 커스텀 뷰에서 읽어올 수 있으며, 필요한 속성 값을 추출한 후 recycle()을 호출하여 메모리를 해제합니다.
- getInt()와 같은 메서드로 속성 값을 읽어오며, 속성 값이 없을 경우 기본값을 설정할 수 있습니다.
이를 통해 attrs.xml에 정의된 속성들이 커스텀 뷰의 동작과 레이아웃에 영향을 미치게 됩니다.
3. 레이아웃 파일에서 사용하기
아래 코드는 리스트 형태의 카드 유형을 적용한 예시입니다.
<com.quessr.playstore_gameview.GameListView
android:id="@+id/listChartGameListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
app:cardType="list"
app:categoryTitleVisibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
app:spanCount="3" />
4. 마무리
GameListView는 LinearLayout을 기반으로 한 커스텀 뷰로, XML에서 다양한 속성을 통해 레이아웃을 쉽게 설정할 수 있습니다. 이러한 속성들은 obtainStyledAttributes 메서드를 통해 읽어와 적용되며, 이를 통해 뷰의 동작과 외형을 유연하게 조정할 수 있습니다.