1. ์ฝ๋ ๋ฆฌ๋ทฐ
(1) App.js
export default function App() {
const [isOpened, setIsOpened]=useState(true);
const [selectedTabIdx, setSelectedTabIdx] = useState(0);
const onPressArrow = () => {
console.log("clicked arrow")
setIsOpened(!isOpened)
}
return (
<View style={styles.container}>
<View style={{
flex: 1,
paddingHorizontal: 15,
}}>
<Header />
<Margin height = {10}/>
<Profile
uri={myProfile.uri}
name={myProfile.name}
introduction={myProfile.introduction}
/>
<Margin height={15}/>
<Division/>
<Margin height={12}/>
<FriendSection
friendProfileLen = {friendProfiles.length}
onPressArrow={onPressArrow}
isOpened = {isOpened}
/>
<FriendList
data = {friendProfiles}
isOpened = {isOpened}
/>
</View>
<TabBar
selectedTabIdx = {selectedTabIdx}
setSelectedTabIdx = {setSelectedTabIdx}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop: statusBarHeight,
},
});
a. tabBar ์ ์ธํ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ view๋ก ํ๋ฒ ๋ ๋ฌถ์๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น View์ flex๋ฅผ 1๋ก ์ง์ ํด์ฃผ์๋ค.
flex: 1์ flex-basis:0, flex-grow: 1, flex-shrink: 1 ๋ก์จ ๊ณ ์ ๋๋น ์์ด ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ๋์ด๋๊ณ ์ค์ด๋ค๊ฒ ๋ค๋ ๋ป์ด๋ค.
๋ง์ฝ์ ํ์ ์์๋ flex๊ฐ ์ง์ ๋์ด ์๋ค๋ฉด ๊ทธ๋ค ์ฌ์ด์ flex ๊ฐ์ ๋น์จ์ ๋ฐ๋ผ ์๋ก ์ฐจ์งํ ๋๋น๊ฐ ์ ํด์ง๋ค.
A ์์์ flex๊ฐ 3์ด๊ณ , B ์์์ flex๊ฐ 7์ด๋ฉด ํด๋น ํ์ ์์๋ค์ 3: 7์ ๋น์จ๋ก ๋๋น๋ฅผ ์ฐจ์ง ํ๋ค.
์ฌ๊ธฐ์๋ tabbar๋ ๋ฐ๋ก flex๋ฅผ ์ ํด์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ ์์ ์ ๊ณ ์ ๋๋น ๋งํผ๋ง ํ๋ฉด์ ์ฐจ์ง ํ๋ค.
๋ฐ๋ผ์ ๋ค๋ฅธ ์์ญ๋ค์ view์ flex:1์ด๋ฏ๋ก ๋๋จธ์ง ์์ญ์ ๋ค ์ฐจ์งํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
b. FriendList์ ScrollView์ ์๋ paddingBottom์ ์ง์ด๋ค.
why? ๋ฆฌ์คํธ์ ํจ๋ฉ ๋ฐํ ์ด ์์๋ ์ด์ ๋ ์คํฌ๋กค ๋๋ ๋ด์ฉ๊ณผ ํฐ ๋ด์ฅ ๋ฒํผ๋ค์ด ์๋ก ๊ฒน์น์ง ์๊ฒ ํ๊ธฐ ์ํด์ ์๋ค.
ํ์ง๋ง TabBar๋ฅผ ์์ฑํ๋ฉด์ ๋ถํฐ, List๋ ์ง์ ์ ์ผ๋ก ํฐ ๋ด์ฅ ๋ฒํผ๋ค๊ณผ ์ ์ด์ด ์์ด์ก๋ค.
์ด์ paddingBottom์ด ์์ผ๋ฉด TabBar์ List ์ฌ์ด์ ์ฌ๋ฐฑ์ด ์๊ฒจ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ง์ ๋ค.
c. selectedTabIdx UseState
0,1,2,3์ ์ํ๋ฅผ ๋ฌ์ ๊ฐ๊ฐ ๋งจ ์ผ์ชฝ๋ถํฐ ๋ฒํผ์ ๋๋ ์ ์ ๋ฐ๋๋ ๊ฐ ๋ค์ด๋ค.
selectedTabIdx์ ํจ์ setSelectedTabIdx ๋ฅผ ์ธ์๋ก TabBar์ ๋ฃ๋๋ค.
(2) TabBar ์ปดํฌ๋ํธ ๋ด๋ถ
export default ({selectedTabIdx, setSelectedTabIdx}) => {
return(
<View style={{
flexDirection: "row",
width: "100%",
padding: bottomSpace,
borderTopWidth: 0.5,
borderTopColor: "grey"
}}>
<TabButton
isSelected={selectedTabIdx === 0}
onPress = {() => setSelectedTabIdx(0)}
activeIconName={"person"}
inactiveIconName= {"persons"}
isIconFontisto
/>
<TabButton
isSelected={selectedTabIdx === 1}
onPress = {() => setSelectedTabIdx(1)}
activeIconName={"chatbubble"}
inactiveIconName= {"chatbubble-outline"}
isIconIonicons
/>
<TabButton
isSelected={selectedTabIdx === 2}
onPress = {() => setSelectedTabIdx(2)}
activeIconName={"pricetag"}
inactiveIconName= {"pricetag-outline"}
isIconIonicons
/>
<TabButton
isSelected={selectedTabIdx === 3}
onPress = {() => setSelectedTabIdx(3)}
activeIconName={"add-circle"}
inactiveIconName= {"add-circle-outline"}
isIconIonicons
/>
</View>
)
}
props๋ก ์ ๋ฐ๊ณ , ์์ฑ ์์ฒด๋ฅผ ์ง์ ๋ฐ์๋ ๋๋ค.
์ด๋ ์ธ์๋ฅผ ์ฌ๋ฌ ๊ฐ ๋ฐ์ ๊ฒฝ์ฐ { }์ผ๋ก ํ ๋ฒ ๊ฐ์ธ์ค์ผ ํ๋ค.
TabBar ๋ด์ flexDirection: "row"๋ก ํด์ ๋ฒํผ์ 4๊ฐ ๋ง๋ ๋ค.
๋ฒํผ์ ์ค๋ณต๋๋ฏ๋ก ๋ฐ๋ก ํจ์๋ก ๋บ๋ค.
const TabButton= ({
isSelected,
onPress,
activeIconName,
inactiveIconName,
isIconFontisto,
isIconIonicons,
}) => {
return(
<TouchableOpacity
activeOpacity={1}
onPress={onPress}
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
paddingVertical: 10,
}}>
{isIconFontisto && <Fontisto name={isSelected? activeIconName : inactiveIconName} size={24} color="black" />}
{isIconIonicons && <Ionicons name={isSelected? activeIconName : inactiveIconName} size={24} color="black" />}
</TouchableOpacity>
)
}
TabButton์ ์ธ์ ์ค๋ช
isSelected๋ ํด๋น ๋ฒํผ์ด ์ ํ๋์๋๊ฐ? ์ด๋ค.
๋๋ฑ ์ฐ์ฐ์ (===)์ ํตํด ํด๋น ๋ฒํผ์ด ๋ํํ๋ ๋๋ฒ๋ฅผ useState ๋ณ์๊ฐ ๊ฐ์ง๊ณ ์๋์ง ํ์ธํ๋ค.
isSelected={selectedTabIdx === 1}
์ํ ๋ณ์๊ฐ 1์ด๋ฉด ์ง๊ธ ๋งจ ์ผ์ชฝ ๋ฒํผ์ด ๋๋ฌ์ ธ์๋ ์ํ ๋ผ๊ณ ๋ณผ ์ ์๋ค.
onPress ํจ์
ํด๋น ๋ฒํผ์ ๋๋ ์ ๋ ๋์ํ๋ ์์ฑ์ด๋ค.
ํจ์๊ฐ ๋๋ฌ์ก๋ค๋ฉด selectedTabIdx๊ฐ ํด๋น ๋ฒํผ์ ๋ํ ๋ฒํธ๋ก ๋ฐ๋์ด์ผ ํ๋ค.
onPress = {() => setSelectedTabIdx(1)}
activeIcon, inActiveIcon
์ ํ ๋์์ ๋๋ ์ ๋์์ ๋๋ ์์ด์ฝ์ด ๋ฌ๋ผ์ผ ํ๋ค.
์ด๋ฅผ ์ผํญ ์ฐ์ฐ์๋ก ๊ตฌํํ๋ค.
name={isSelected? activeIconName : inactiveIconName}
isIconFontisto, isIconIonicons
์์ด์ฝ์ ์์ ํด์จ ๋ฒ์ง ์๊ฐ ์๋ก ํ๋ฆฌ๋ค. ๋ฐ๋ผ์
์์ ์ปดํฌ๋ํธ์์ ๋ฌด์จ ์์ด์ฝ ์ฌ์ฉํ๋์ง ๋ฐ๊ณ ๊ทธ ์์ด์ฝ์ ์ฌ์ฉํ๋ฉด ํ์ ์ปดํฌ๋ํธ์์ ํด๋น ์์ด์ฝ์ผ๋ก ์์ ํ๋๋ก ํด์ผํ๋ค.
๋จผ์ ์์ ์ปดํฌ๋ํธ์์ ์ด๋ค ์ข ๋ฅ์ ์์ด์ฝ ์ฌ์ฉํ๋์ง๋ ๋ค์๊ณผ ๊ฐ์ด ๋ํ๋ธ๋ค.
<TabButton
isSelected={selectedTabIdx === 1}
onPress = {() => setSelectedTabIdx(1)}
activeIconName={"chatbubble"}
inactiveIconName= {"chatbubble-outline"}
isIconIonicons
/>
ํด๋น button์ Ionicons๋ฅผ ์ฐ๋ ๊ฒ์ ์ ์ ์๋ค.
์์ ๊ฐ์ด ๊ทธ๋ฅ ์์ฑ ์์ฒด๋ฅผ ์ ์ด๋๋ ๊ฒ๋ง์ผ๋ก๋ true ์ด๋ค.
์์ฑ์ด ์ ์ ํ ์์ผ๋ฉด false ์ด๋ค.
์ ๋ด์ฉ์ TabButton ๋ด๋ถ ๋ก์ง์ด๊ณ , ๋ง์ฝ Fontisoicon ์ฐ๋ฉด ์์๊บผ ๋ฐ๋, Ionicon ์ฐ๋ฉด ๋ฐ์ ๊ฑฐ ๋ฐ๋์ด๋ค.
** ์ฐธ๊ณ **
์ด๋ ๊ฒ ์ ์ผ๋ฉด, TouchOpacity ํ๊ทธ ๋๋ ์ ๋๋ ์ ํ๋ ค์ง๋ค. ๋ถํฌ๋ช ๋๋ฅผ 100%๋ก ํ ๊ฒ
2. ์ง์ ํด๋ณด๊ธฐ
1. main ๋งค์๋์์ tabBar์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค ๊ฐ์ ํฌ๊ธฐ ์กฐ์ (ํญ๋ฐ- ๊ณ ์ ๋ถ๋ณ, ๋ค๋ฅธ ๋ฉ์๋๋ค ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ์ ๊ฐ๋ณ์ )
2. List์ paddingBottom ์ง์ฐ๊ธฐ. (tabBar์์ ๊ณต๋ฐฑ ์์ ๊ธฐ)
3. ์ํํจ์ ๋ง๋ค์ด์ TabBar์ ๋์
4. TabBar์์ ํ๋ฒํผ ๋ง๋ค๊ธฐ. (๋๋ ค์ก์ ๋ ์๋ ๋ ๋ค๋ฅธ ์์ด์ฝ / ๋๋ ์ ๋ ํ๋ ค์ง๋ ๊ฒ ์์ ๊ธฐ)
์์ฑ ์ ๋๋ก ๋์๊ฐ!
์ฃผ์ํ ์
์ปดํฌ๋ํธ์ ์ธ์๋ก ๊ฐ์ด ๋ณต์๋ก ๋ค์ด์ฌ ๊ฒฝ์ฐ
{}๋ก ๊ฐ์ ๊ฒ