Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation 구현 #17

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions app/src/main/kotlin/com/yourssu/handy/demo/NavigationPreview.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.yourssu.handy.demo

import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.yourssu.handy.compose.BottomNavItem
import com.yourssu.handy.compose.Navigation
import com.yourssu.handy.compose.icons.HandyIcons
import com.yourssu.handy.compose.icons.filled.Home

@Preview(showBackground = true)
@Composable
fun NavigationPreview() {
val items = listOf(
BottomNavItem(
icon = HandyIcons.Filled.Home,
label = null
),
BottomNavItem(
icon = HandyIcons.Filled.Home,
label = "Label"
),
BottomNavItem(
icon = HandyIcons.Filled.Home,
label = "Label"
),
BottomNavItem(
icon = HandyIcons.Filled.Home,
label = "Label"
),
BottomNavItem(
icon = HandyIcons.Filled.Home,
label = "Label"
),
)

Navigation(
items = items,
selectedIndex = 0,
onItemSelected = {}
)
}
109 changes: 109 additions & 0 deletions compose/src/main/kotlin/com/yourssu/handy/compose/Navigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.yourssu.handy.compose

import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import com.yourssu.handy.compose.foundation.HandyTypography

/**
* BottomNavItem : 하단 네비게이션 바의 아이템을 정의하는 데이터 클래스 입니다.
*
* @param icon 아이템의 아이콘
* @param label 아이템의 라벨
*/
data class BottomNavItem(
val icon: ImageVector,
val label: String?
)

/**
* BottomNavItem : 하단 네비게이션 바의 아이템 Composable 함수 입니다.
*
* @param item 하단 네비게이션 바의 아이템
* @param isSelected 선택되었는지 여부
* @param onClick 클릭 시 실행되는 함수
* @param modifier Modifier
*/
@Composable
private fun BottomNavItem(
item: BottomNavItem,
isSelected: Boolean,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSelected에 기본값이 있고 없고는 큰 상관이 없겠죠??

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보통 false긴 한데 큰 상관없을듯합니다

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Row(
            modifier = Modifier.fillMaxSize(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            items.forEachIndexed { index, item ->
                BottomNavItem(
                    item = item,
                    isSelected = index == selectedIndex,
                    modifier = Modifier.weight(1f),
                    onClick = { onItemSelected(index) }
                )
            }
        }

사용자가 지정할 일이 없고 상태가 저장되는 selectedIndex에 의해 선택 여부가 정해지기 때문입니다

onClick: () -> Unit,
modifier: Modifier = Modifier
) {
val color =
if (isSelected) HandyTheme.colors.textBasicPrimary else HandyTheme.colors.textBasicDisabled

Column(
modifier = modifier
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onClick
),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Icon(
item.icon,
iconSize = IconSize.M,
)

if (item.label != null) {
Text(
text = item.label,
style = HandyTypography.C1Rg11,
color = color
)
}
}
}

/**
* Navigation : 하단 네비게이션 바 Composable 함수 입니다.
*
* @param items 하단 네비게이션 바의 아이템 리스트
* @param selectedIndex 선택된 아이템의 인덱스
* @param onItemSelected 아이템 선택 시 실행되는 함수
*/
@Composable
fun Navigation(
items: List<BottomNavItem>,
selectedIndex: Int,
onItemSelected: (Int) -> Unit
) {
require(items.size in 3..5) { "Items size must be between 3 and 5" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 items수를 강제하는 건 좋은 것 같긴한데 require를 사용하게 되면
해당 컴포넌트로 개발 진행 시에 item수 미달, 초과로 preview단에서 오류가 뜨면 추적이 어려울 것 같은데 어떻게 생각하시나요??
item을 6개 넣으면 preview render오류가 뜨긴하지만 메시지는 보이지 않네요,,
image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
이슈 패널 열면 뜨고 에뮬레이터에 돌리면 에러가 납니다.


Column(
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
) {
// Divider(thickness = Thickness.Thin) // Divider 추후 추가
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

divider 머지 후 이부분도 수정 확인 위해서 코멘트 남겨두겠습니다

Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
items.forEachIndexed { index, item ->
BottomNavItem(
item = item,
isSelected = index == selectedIndex,
modifier = Modifier.weight(1f),
onClick = { onItemSelected(index) }
)
}
}
}
}