화어하모니OS 개발: Tabs 컴포넌트 심층 가이드
소개
모바일 앱 디자인에서 탭(Tabs)은 사용자가 다른 콘텐츠 영역을 전환하는 데 중요한 인터페이스 요소입니다. 화어하모니OS 운영체제에서 제공하는 Tabs 컴포넌트는 개발자가 고도로 맞춤화된 탭 인터페이스를 생성할 수 있도록 지원합니다. 본문에서는 DevEco Studio를 통해 Tabs 컴포넌트의 사용법을 상세히 소개하며, 기본 설정, 동적 탭 생성, 그리고 고유한 시각 효과를 구현하기 위한 커스텀 컴포넌트 활용 방법을 다룹니다.
Tabs 컴포넌트 기초
Tabs 컴포넌트는 개발자가 스크롤 가능한 탭 그룹을 생성하고 각 탭에 해당하는 다른 콘텐츠 영역을 연결할 수 있게 해줍니다.
기본 사용법
예제 1: 기본 Tabs 탭 생성
@Entry
@Component
struct MainView {
build() {
Tabs() {
TabContent() {
Text('탐색 콘텐츠') // 단 하나의 자식 컴포넌트만 허용
}
.tabBar('탐색') // 네비게이션 설정
TabContent() {
Text('트렌드 콘텐츠') // 단 하나의 자식 컴포넌트만 허용
}
.tabBar('트렌드')
TabContent() {
Text('핫토픽 콘텐츠') // 단 하나의 자식 컴포넌트만 허용
}
.tabBar('핫토픽')
TabContent() {
Text('프로필 콘텐츠') // 단 하나의 자식 컴포넌트만 허용
}
.tabBar('프로필')
}
}
}
이 예제에서는 네 개의 탭을 포함하는 Tabs 컴포넌트를 생성했으며, 각 탭은 서로 다른 주제의 텍스트 콘텐츠를 표시합니다.
네비게이션 설정
예제 2: Tabs 네비게이션 속성 설정
@Entry
@Component
struct MainView {
build() {
Tabs({
barPosition: BarPosition.Start // 네비게이션 위치
})
{
TabContent() {
Text('탐색 콘텐츠')
}
.tabBar('탐색')
TabContent() {
Text('트렌드 콘텐츠')
}
.tabBar('트렌드')
TabContent() {
Text('핫토픽 콘텐츠')
}
.tabBar('핫토픽')
TabContent() {
Text('프로필 콘텐츠')
}
.tabBar('프로필')
}
.vertical(false) // 네비게이션 수직/수평 설정
.scrollable(false) // 제스처 스크롤 활성화 여부
.animationDuration(0) // 클릭 시 슬라이딩 애니메이션 시간
}
}
이 예제에서는 Tabs 컴포넌트의 네비게이션 속성을 설정했으며, 네비게이션 위치, 스크롤 제스처 및 애니메이션 시간이 포함됩니다.
동적 Tabs 생성
예제 3: ForEach를 사용한 동적 Tabs 생성
@Entry
@Component
struct MainView {
tabTitles: string[] = [
'탐색', '트렌드', '핫토픽', '기술', '엔터테인먼트',
'스포츠', '교육', '건강', '금융', '여행'
]
build() {
Tabs() {
ForEach(this.tabTitles, (title: string, index) => {
TabContent() {
Text(`${title} 콘텐츠`)
}
.tabBar(title)
})
}
.barMode(BarMode.Scrollable) // 스크롤 가능한 네비게이션 바 구현
}
}
이 예제에서는 ForEach 루프를 사용하여 10개의 탭을 동적으로 생성했으며, 각 탭의 제목은 tabTitles 배열에서 가져옵니다.
Tabs 스타일 커스터마이징
예제 4: Tabs 스타일 커스터마이징
@Entry
@Component
struct MainView {
@Builder
customTabBuilder(title: string, icon: ResourceStr) {
Column() {
Image(icon)
.width(30)
Text(title)
}
}
build() {
Tabs({
barPosition: BarPosition.End
})
{
TabContent() {
Text('메시지 콘텐츠')
}
.tabBar(this.customTabBuilder('메시지', $r('app.media.icon_message')))
TabContent() {
Text('설정 콘텐츠')
}
.tabBar(this.customTabBuilder('설정', $r('app.media.icon_settings')))
}
}
}
이 예제에서는 @Builder 함수 customTabBuilder를 정의하여 각 탭의 스타일을 커스터마이징하며, 이미지와 텍스트를 포함합니다.
상태 관리
예제 5: Tabs 활성 상태 관리
@Entry
@Component
struct MainView {
@State activeIndex: number = 0
@Builder
customTabBuilder(itemIndex: number, title: string, normalIcon: ResourceStr, activeIcon: ResourceStr) {
Column() {
Image(itemIndex == this.activeIndex ? activeIcon : normalIcon)
.width(30)
Text(title)
.fontColor(itemIndex == this.activeIndex ? Color.Red : Color.Black)
}
}
build() {
Tabs()
{
TabContent() {
Text('메시지 콘텐츠')
}
.tabBar(this.customTabBuilder(0, '메시지', $r('app.media.icon_message'), $r('app.media.icon_message_active')))
TabContent() {
Text('설정 콘텐츠')
}
.tabBar(this.customTabBuilder(1, '설정', $r('app.media.icon_settings'), $r('app.media.icon_settings_active')))
}
.onChange((index: number) => {
this.activeIndex = index
})
.animationDuration(0)
.scrollable(false)
}
}
이 예제에서는 @State 속성 activeIndex를 사용하여 현재 활성화된 탭의 인덱스를 저장하고, onChange 이벤트에서 이 인덱스를 업데이트합니다.
특수 모양의 탭
예제 6: 특수 모양의 탭 추가
@Entry
@Component
struct MainView {
@State activeIndex: number = 0
@Builder
customTabBuilder(itemIndex: number, title: string, normalIcon: ResourceStr, activeIcon: ResourceStr) {
Column() {
Image(itemIndex == this.activeIndex ? activeIcon : normalIcon)
.width(30)
Text(title)
.fontColor(itemIndex == this.activeIndex ? Color.Red : Color.Black)
}
}
@Builder
specialTabBuilder() {
Image($r('app.media.special_icon'))
.width(40)
.margin({ bottom: 10 })
}
build() {
Tabs()
{
TabContent() {
Text('홈 콘텐츠')
}
.tabBar(this.customTabBuilder(0, '홈', $r('app.media.icon_home'), $r('app.media.icon_home_active')))
TabContent() {
Text('카테고리 콘텐츠')
}
.tabBar(this.customTabBuilder(1, '카테고리', $r('app.media.icon_category'), $r('app.media.icon_category_active')))
TabContent() {
Text('이벤트 콘텐츠')
}
.tabBar(this.specialTabBuilder())
TabContent() {
Text('장바구니 콘텐츠')
}
.tabBar(this.customTabBuilder(3, '장바구니', $r('app.media.icon_cart'), $r('app.media.icon_cart_active')))
TabContent() {
Text('프로필 콘텐츠')
}
.tabBar(this.customTabBuilder(4, '프로필', $r('app.media.icon_profile'), $r('app.media.icon_profile_active')))
}
.onChange((index: number) => {
this.activeIndex = index
})
.animationDuration(0)
.scrollable(false)
}
}
이 예제에서는 특수 모양의 탭을 추가하고 specialTabBuilder 함수를 사용하여 그 스타일을 커스터마이징합니다.