Skip to content

Commit 9ab1a76

Browse files
authored
Top Bar 구현 (#19)
* 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: 구현 방식 변경
1 parent 807b5f2 commit 9ab1a76

File tree

2 files changed

+273
-0
lines changed

2 files changed

+273
-0
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.yourssu.handy.demo
2+
3+
import android.util.Log
4+
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.Spacer
7+
import androidx.compose.foundation.layout.height
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.tooling.preview.Preview
11+
import androidx.compose.ui.unit.dp
12+
import com.yourssu.handy.compose.CenterAlignedTopAppBar
13+
import com.yourssu.handy.compose.HandyTheme
14+
import com.yourssu.handy.compose.Icon
15+
import com.yourssu.handy.compose.LeftAlignedTopAppBar
16+
import com.yourssu.handy.compose.Text
17+
import com.yourssu.handy.compose.icons.HandyIcons
18+
import com.yourssu.handy.compose.icons.line.Add
19+
import com.yourssu.handy.compose.icons.line.ArrowsChevronLeft
20+
21+
@Preview(showBackground = true)
22+
@Composable
23+
fun CenterAlignedTopAppBarPreview() {
24+
Column {
25+
CenterAlignedTopAppBar(
26+
title = "Centered",
27+
navIcon = HandyIcons.Line.ArrowsChevronLeft,
28+
onNavIconClick = { Log.d("TopBarPreview", "ArrowsChevronLeft clicked") },
29+
actions = {}
30+
)
31+
32+
Spacer(modifier = Modifier.height(10.dp))
33+
34+
CenterAlignedTopAppBar(
35+
title = "Back Example",
36+
navIcon = HandyIcons.Line.ArrowsChevronLeft,
37+
onNavIconClick = { Log.d("TopBarPreview", "ArrowsChevronLeft clicked") },
38+
actions = {
39+
Text(
40+
text = "Share",
41+
color = HandyTheme.colors.textBrandPrimary,
42+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Share clicked") })
43+
}
44+
)
45+
46+
Spacer(modifier = Modifier.height(10.dp))
47+
48+
CenterAlignedTopAppBar(
49+
title = "최대8자까지가능",
50+
navIcon = HandyIcons.Line.ArrowsChevronLeft,
51+
onNavIconClick = { Log.d("TopBarPreview", "ArrowsChevronLeft clicked") },
52+
actions = {
53+
Icon(
54+
imageVector = HandyIcons.Line.Add,
55+
contentDescription = "Add",
56+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
57+
)
58+
Text(
59+
text = "Text",
60+
color = HandyTheme.colors.textBrandPrimary,
61+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Share clicked") })
62+
63+
}
64+
)
65+
}
66+
}
67+
68+
69+
@Preview(showBackground = true)
70+
@Composable
71+
fun LeftAlignedTopBarPreview() {
72+
Column {
73+
LeftAlignedTopAppBar(
74+
title = "Title",
75+
actions = {}
76+
)
77+
78+
Spacer(modifier = Modifier.height(10.dp))
79+
80+
LeftAlignedTopAppBar(
81+
title = "Title",
82+
actions = {
83+
Icon(
84+
imageVector = HandyIcons.Line.Add,
85+
contentDescription = "Add",
86+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
87+
)
88+
}
89+
)
90+
91+
Spacer(modifier = Modifier.height(10.dp))
92+
93+
LeftAlignedTopAppBar(
94+
title = "Title",
95+
actions = {
96+
Icon(
97+
imageVector = HandyIcons.Line.Add,
98+
contentDescription = "Add",
99+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
100+
)
101+
Icon(
102+
imageVector = HandyIcons.Line.Add,
103+
contentDescription = "Add",
104+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
105+
)
106+
}
107+
)
108+
109+
Spacer(modifier = Modifier.height(10.dp))
110+
111+
LeftAlignedTopAppBar(
112+
title = "Title",
113+
actions = {
114+
Icon(
115+
imageVector = HandyIcons.Line.Add,
116+
contentDescription = "Add",
117+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
118+
)
119+
Icon(
120+
imageVector = HandyIcons.Line.Add,
121+
contentDescription = "Add",
122+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
123+
)
124+
Icon(
125+
imageVector = HandyIcons.Line.Add,
126+
contentDescription = "Add",
127+
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") }
128+
)
129+
}
130+
)
131+
}
132+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.yourssu.handy.compose
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.RowScope
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.fillMaxHeight
11+
import androidx.compose.foundation.layout.fillMaxWidth
12+
import androidx.compose.foundation.layout.height
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.ui.Alignment
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.graphics.vector.ImageVector
18+
import androidx.compose.ui.text.style.TextAlign
19+
import androidx.compose.ui.unit.dp
20+
import com.yourssu.handy.compose.TopBarDefaults.topBarActionsInsidePadding
21+
import com.yourssu.handy.compose.TopBarDefaults.topBarHeight
22+
import com.yourssu.handy.compose.TopBarDefaults.topBarHorizontalPadding
23+
import com.yourssu.handy.compose.TopBarDefaults.topBarIconPadding
24+
import com.yourssu.handy.compose.foundation.HandyTypography
25+
26+
27+
/**
28+
* Center-Aligned Top App Bar
29+
*
30+
* 타이틀이 중앙에 위치한 탑앱바입니다. 좌측에 메뉴 아이콘 및 뒤로 가기 아이콘이 요구될 경우 사용합니다.
31+
* 아이콘으로 기능을 명확하게 표현하지 못하거나 확실하게 기능을 설명하고 싶을 때 아이콘 대신 Text를 사용할 수 있습니다.
32+
* 이때, 텍스트의 사용은 한 개까지만 가능하며, 텍스트가 공백 포함 5자일 경우 우측에 아이콘을 같이 쓸 수 없습니다.
33+
*
34+
*
35+
* @param title headline or Logo 최대 9자(공백 포함)
36+
* @param navIcon 왼쪽 아이콘
37+
* @param actions 오른쪽 아이콘 or 텍스트 (아이콘은 임의로 변경할 수 있으며 Center-aligned의 우측엔 최대 2개의 아이콘 버튼)
38+
**/
39+
@Composable
40+
fun CenterAlignedTopAppBar(
41+
title: String,
42+
navIcon: ImageVector,
43+
onNavIconClick: () -> Unit,
44+
modifier: Modifier = Modifier,
45+
actions: @Composable (RowScope.() -> Unit)? = null
46+
) {
47+
Box(
48+
modifier = modifier
49+
.fillMaxWidth()
50+
.background(color = HandyTheme.colors.bgBasicDefault)
51+
.height(topBarHeight) //Top App Bar의 높이값을 임의로 변경하지 않습니다.
52+
.padding(horizontal = topBarHorizontalPadding),
53+
contentAlignment = Alignment.Center
54+
) {
55+
56+
// CenterAligned 일 때는 좌측 아이콘이 항상 있음.
57+
Box(
58+
modifier = Modifier
59+
.align(Alignment.CenterStart)
60+
) {
61+
Icon(
62+
imageVector = navIcon,
63+
modifier = Modifier
64+
.clickable { onNavIconClick() }
65+
.padding(topBarIconPadding) // 터치영역을 8dp만큼 확장
66+
)
67+
}
68+
69+
Text(
70+
text = title,
71+
color = HandyTheme.colors.textBasicPrimary,
72+
style = HandyTypography.T2Sb18,
73+
textAlign = TextAlign.Center,
74+
)
75+
76+
actions?.let {
77+
Row(
78+
verticalAlignment = Alignment.CenterVertically,
79+
horizontalArrangement = Arrangement.spacedBy(topBarActionsInsidePadding), // 요소 사이에 24dp 간격 추가
80+
modifier = Modifier.fillMaxHeight()
81+
) {
82+
Spacer(modifier = Modifier.weight(1f))
83+
actions()
84+
}
85+
}
86+
}
87+
}
88+
89+
90+
/**
91+
* Left-aligned
92+
*
93+
* 타이틀이 좌측에 위치한 탑앱바입니다. 기능의 첫 페이지에 사용되는 탑앱바로,
94+
* 현재 페이지의 제목을 나타낼 때 사용합니다. 아이콘으로 기능을 명확하게 표현하지 못하거나 확실하게 기능을 설명하고 싶을 때 아이콘 대신 Text를 사용할 수 있습니다.
95+
*
96+
* @param title headline or Logo 최대 9자(공백 포함)
97+
* @param actions 오른쪽 아이콘 or 텍스트 (아이콘은 임의로 변경할 수 있으며 Left-aligned의 우측엔 최대 3개의 아이콘 버튼)
98+
**/
99+
@Composable
100+
fun LeftAlignedTopAppBar(
101+
title: String,
102+
actions: @Composable (RowScope.() -> Unit)? = null
103+
) {
104+
105+
Box(
106+
modifier = Modifier
107+
.fillMaxWidth()
108+
.background(color = HandyTheme.colors.bgBasicDefault)
109+
.height(topBarHeight)
110+
.padding(horizontal = topBarHorizontalPadding),
111+
112+
contentAlignment = Alignment.Center
113+
) {
114+
115+
Text(
116+
text = title,
117+
style = HandyTypography.H3Sb24,
118+
color = HandyTheme.colors.textBasicPrimary,
119+
modifier = Modifier.align(Alignment.CenterStart)
120+
121+
)
122+
123+
actions?.let {
124+
Row(
125+
verticalAlignment = Alignment.CenterVertically,
126+
horizontalArrangement = Arrangement.spacedBy(topBarActionsInsidePadding), // 요소 사이에 24dp 간격 추가
127+
) {
128+
Spacer(modifier = Modifier.weight(1f))
129+
actions()
130+
}
131+
}
132+
}
133+
}
134+
135+
136+
object TopBarDefaults {
137+
val topBarHeight = 56.dp
138+
val topBarHorizontalPadding = 16.dp
139+
val topBarActionsInsidePadding = 24.dp
140+
val topBarIconPadding = 8.dp
141+
}

0 commit comments

Comments
 (0)