Skip to content

Commit

Permalink
Top Bar 구현 (#19)
Browse files Browse the repository at this point in the history
* add: TopBar

* feat: CenterAlignedTopBar NavIcon

* feat: CenterAlignedTopBar actions

* feat: LeftAlignedTopAppBar

* feat: top bar 다듬기

* feat: text BrandPrimary로

* chore: modifier 인자로 받아온 걸로 교체 (#20)

* Add .idea/* to gitignore (#22)

* chore: add ".idea/*" to gitignore

* chore: /.idea

* chore: .idea

* chore: /.idea

* delete: .idea/*

* clean

* add: TopBar

* feat: CenterAlignedTopBar NavIcon

* feat: CenterAlignedTopBar actions

* feat: LeftAlignedTopAppBar

* feat: top bar 다듬기

* feat: text BrandPrimary로

* chore: 메소드 위치 조정

* feat: actions sealed interface로 구현

* chore: 상수화

* feat: 구현 방식 변경
  • Loading branch information
HI-JIN2 authored Jan 19, 2025
1 parent 807b5f2 commit 9ab1a76
Show file tree
Hide file tree
Showing 2 changed files with 273 additions and 0 deletions.
132 changes: 132 additions & 0 deletions app/src/main/kotlin/com/yourssu/handy/demo/TopBarPreview.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.yourssu.handy.demo

import android.util.Log
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.yourssu.handy.compose.CenterAlignedTopAppBar
import com.yourssu.handy.compose.HandyTheme
import com.yourssu.handy.compose.Icon
import com.yourssu.handy.compose.LeftAlignedTopAppBar
import com.yourssu.handy.compose.Text
import com.yourssu.handy.compose.icons.HandyIcons
import com.yourssu.handy.compose.icons.line.Add
import com.yourssu.handy.compose.icons.line.ArrowsChevronLeft

@Preview(showBackground = true)
@Composable
fun CenterAlignedTopAppBarPreview() {
Column {
CenterAlignedTopAppBar(
title = "Centered",
navIcon = HandyIcons.Line.ArrowsChevronLeft,
onNavIconClick = { Log.d("TopBarPreview", "ArrowsChevronLeft clicked") },
actions = {}
)

Spacer(modifier = Modifier.height(10.dp))

CenterAlignedTopAppBar(
title = "Back Example",
navIcon = HandyIcons.Line.ArrowsChevronLeft,
onNavIconClick = { Log.d("TopBarPreview", "ArrowsChevronLeft clicked") },
actions = {
Text(
text = "Share",
color = HandyTheme.colors.textBrandPrimary,
modifier = Modifier.clickable { Log.d("TopBarPreview", "Share clicked") })
}
)

Spacer(modifier = Modifier.height(10.dp))

CenterAlignedTopAppBar(
title = "최대8자까지가능",
navIcon = HandyIcons.Line.ArrowsChevronLeft,
onNavIconClick = { Log.d("TopBarPreview", "ArrowsChevronLeft clicked") },
actions = {
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
Text(
text = "Text",
color = HandyTheme.colors.textBrandPrimary,
modifier = Modifier.clickable { Log.d("TopBarPreview", "Share clicked") })

}
)
}
}


@Preview(showBackground = true)
@Composable
fun LeftAlignedTopBarPreview() {
Column {
LeftAlignedTopAppBar(
title = "Title",
actions = {}
)

Spacer(modifier = Modifier.height(10.dp))

LeftAlignedTopAppBar(
title = "Title",
actions = {
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
}
)

Spacer(modifier = Modifier.height(10.dp))

LeftAlignedTopAppBar(
title = "Title",
actions = {
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
}
)

Spacer(modifier = Modifier.height(10.dp))

LeftAlignedTopAppBar(
title = "Title",
actions = {
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
Icon(
imageVector = HandyIcons.Line.Add,
contentDescription = "Add",
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
)
}
)
}
}
141 changes: 141 additions & 0 deletions compose/src/main/kotlin/com/yourssu/handy/compose/TopAppBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.yourssu.handy.compose

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.yourssu.handy.compose.TopBarDefaults.topBarActionsInsidePadding
import com.yourssu.handy.compose.TopBarDefaults.topBarHeight
import com.yourssu.handy.compose.TopBarDefaults.topBarHorizontalPadding
import com.yourssu.handy.compose.TopBarDefaults.topBarIconPadding
import com.yourssu.handy.compose.foundation.HandyTypography


/**
* Center-Aligned Top App Bar
*
* 타이틀이 중앙에 위치한 탑앱바입니다. 좌측에 메뉴 아이콘 및 뒤로 가기 아이콘이 요구될 경우 사용합니다.
* 아이콘으로 기능을 명확하게 표현하지 못하거나 확실하게 기능을 설명하고 싶을 때 아이콘 대신 Text를 사용할 수 있습니다.
* 이때, 텍스트의 사용은 한 개까지만 가능하며, 텍스트가 공백 포함 5자일 경우 우측에 아이콘을 같이 쓸 수 없습니다.
*
*
* @param title headline or Logo 최대 9자(공백 포함)
* @param navIcon 왼쪽 아이콘
* @param actions 오른쪽 아이콘 or 텍스트 (아이콘은 임의로 변경할 수 있으며 Center-aligned의 우측엔 최대 2개의 아이콘 버튼)
**/
@Composable
fun CenterAlignedTopAppBar(
title: String,
navIcon: ImageVector,
onNavIconClick: () -> Unit,
modifier: Modifier = Modifier,
actions: @Composable (RowScope.() -> Unit)? = null
) {
Box(
modifier = modifier
.fillMaxWidth()
.background(color = HandyTheme.colors.bgBasicDefault)
.height(topBarHeight) //Top App Bar의 높이값을 임의로 변경하지 않습니다.
.padding(horizontal = topBarHorizontalPadding),
contentAlignment = Alignment.Center
) {

// CenterAligned 일 때는 좌측 아이콘이 항상 있음.
Box(
modifier = Modifier
.align(Alignment.CenterStart)
) {
Icon(
imageVector = navIcon,
modifier = Modifier
.clickable { onNavIconClick() }
.padding(topBarIconPadding) // 터치영역을 8dp만큼 확장
)
}

Text(
text = title,
color = HandyTheme.colors.textBasicPrimary,
style = HandyTypography.T2Sb18,
textAlign = TextAlign.Center,
)

actions?.let {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(topBarActionsInsidePadding), // 요소 사이에 24dp 간격 추가
modifier = Modifier.fillMaxHeight()
) {
Spacer(modifier = Modifier.weight(1f))
actions()
}
}
}
}


/**
* Left-aligned
*
* 타이틀이 좌측에 위치한 탑앱바입니다. 기능의 첫 페이지에 사용되는 탑앱바로,
* 현재 페이지의 제목을 나타낼 때 사용합니다. 아이콘으로 기능을 명확하게 표현하지 못하거나 확실하게 기능을 설명하고 싶을 때 아이콘 대신 Text를 사용할 수 있습니다.
*
* @param title headline or Logo 최대 9자(공백 포함)
* @param actions 오른쪽 아이콘 or 텍스트 (아이콘은 임의로 변경할 수 있으며 Left-aligned의 우측엔 최대 3개의 아이콘 버튼)
**/
@Composable
fun LeftAlignedTopAppBar(
title: String,
actions: @Composable (RowScope.() -> Unit)? = null
) {

Box(
modifier = Modifier
.fillMaxWidth()
.background(color = HandyTheme.colors.bgBasicDefault)
.height(topBarHeight)
.padding(horizontal = topBarHorizontalPadding),

contentAlignment = Alignment.Center
) {

Text(
text = title,
style = HandyTypography.H3Sb24,
color = HandyTheme.colors.textBasicPrimary,
modifier = Modifier.align(Alignment.CenterStart)

)

actions?.let {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(topBarActionsInsidePadding), // 요소 사이에 24dp 간격 추가
) {
Spacer(modifier = Modifier.weight(1f))
actions()
}
}
}
}


object TopBarDefaults {
val topBarHeight = 56.dp
val topBarHorizontalPadding = 16.dp
val topBarActionsInsidePadding = 24.dp
val topBarIconPadding = 8.dp
}

0 comments on commit 9ab1a76

Please sign in to comment.