1. Scroll View ์ FlatList์ ์ฐจ์ด์ .
ScrollView๋ ํ๋ฉด์ ๋ณด์ด์ง ์๋ ๋ถ๋ถ๋ ๋ค ๋๋๋งํ์ฌ ๋ง๋ค์ด ๋๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์๊ฐ ํ๋ฉด์์ ๋ฒ์ด๋๋ ๋ถ๋ถ์ ๋ณด๊ณ ์ถ์ผ๋ฉด, ์คํฌ๋กค ํด์ ๋ณผ ์ ์๊ฒ ๋ง๋ ๋ค. ๋ฐ์ดํฐ ์์ด ๋ง์ง ์๊ณ ๊ณ ์ ์ ์ผ ๋ ์ฌ์ฉํ๋ค.
๋ฐ๋ฉด FlatList๋ ํ๋ฉด์ ๋ณด์ด๋ ๋ถ๋ถ๋ง ๋๋๋งํ์ฌ ๋ง๋ค์ด ๋๋๋ค. ๋ง์ฝ ์ฌ์ฉ์๊ฐ ๋ณด์ด์ง ์๋ ๋ถ๋ถ์ ๋ณด๊ณ ์ถ์ด ์คํฌ๋กค ํ ์ ๊ทธ ๋ ์ ๋ง๋ค์ด ๋์ ๋ด์ฉ๋ค์ ๋ง๋ ๋ค. ๋ฏธ๋ฆฌ ๋ชจ๋ ๋ด์ฉ์ ๋ง๋ค์ด ๋๋ Scroll View์ ๋น๊ตํ์ ๋ ์๋์ ์ผ๋ก ์ข์ ์ฑ๋ฅ์ ๋ณด์ธ๋ค.
2. ์ฝ๋ ๋ฆฌ๋ทฐ
(1) FlatList์ ์์ฑ๋ค ๋ฏ์ด๋ณด๊ธฐ
<FlatList
data={isOpened ? friendProfiles : []}
contentContainerStyle = {{paddingHorizontal: 15,}}
keyExtractor={(_, index) => index}
ItemSeparatorComponent={ItemSeparatorComponent}
stickyHeaderIndices={[0]}
renderItem={renderItem}
ListHeaderComponent={ListHeaderComponent}
ListFooterComponent={ListFooterComponent}
showsVerticalScrollIndicator ={false}
>
a. Data
: FlatList์์ ์คํฌ๋กค ๋๋ ๋ณธ๋ฌธ(body) ๋ด์ฉ์ด ๋ค์ด๊ฐ๋ ๊ณณ
b. contentCotainerStyle
: ์ด๊ฑด ์ ๋ฒ ScrollView ์์๋ ๋ดค๋ฏ์ด, scroll ๋๋ ๊ณณ์ ๋ด์ฉ๋ฌผ์๊ฒ ์คํ์ผ์ ์ ์ฉํ๋ ์์ฑ์ด๋ค.
์คํฌ๋กค ๋ทฐ๋ flatlist๋ ํ์ฌ ๋ณด์ฌ์ง๋ ๋ถ๋ถ์ ํ๊ณผ, ์คํฌ๋กค๋๋ ๋ด์ฉ๋ค์ด ๋ณ๊ฐ๋ก ์กด์ฌํ๋ค.
๋ฐ๋ผ์ ๊ทธ๋ฅ style์ ์ ์ฉํ๋ฉด, ์ ํ์ฌ ๋ณด์ฌ์ง๋ ๋ถ๋ถ์ ํ์ ์์ฉํ๋ค.
c. KeyExtractor
: ScrollView์์ Map์ด๋ผ๋ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ, data์ ์ ๋ณด๋ค์ ํ๋์ฉ ๊ฐ์ ธ์์ ScrollView์ ๋ด์์๋ค.
Map ํจ์๋ data.js์ ์๋ ๋ฐฐ์ด์ ๋ฐ์ดํฐ ์์๋ค์ ์ฐจ๋ก๋๋ก ๊ฐ์ ธ์์ () ์์ ๋ก์ง์ ์ํํ๋ค.
์ด๋ Map์ ํจ์ ๋ด์ฉ ์ต์๋จ์ ๊ฐ๋ค์ ๋ํ Key๋ฅผ ์ ์ด์ค์ผ ํ๋ค. Key๋ Value ๋ง๋ค ๊ณ ์ ํด์ผ ํ๋ฏ๋ก, ์ฌ๊ธฐ์๋ index๋ฅผ ์ฌ์ฉํ์๋ค. flatList๋ ๋ง์ฐฌ๊ฐ์ง๊ณ renderItem์ด๋ ํจ์๋ฅผ ๋ง๋ค์ด map ๊ณผ ๊ฐ์ด ์์ง์ด๋๋ก ํ๋ค. renderItem๋ key ๊ฐ์ ์ต์๋จ์ ์จ์ค์ผ ํ๋ค. ํ์ง๋ง FlatList๋ Key ๊ฐ ์ ๋ ์์ฑ์ ๋ฐ๋ก ๋ ์ ์๊ณ ์ฌ๊ธฐ๋ค๊ฐ ์ ์ ์ renderItem ๋ด๋ถ์ ์ ์จ์ค๋ ๋๋ค. ์ด๊ฒ์ด KeyExtractor ์ด๋ค.
d. ItemSeparatorComponent
: ๋ฐ์ดํฐ ๊ฐ๋ค ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ฅผ ์ผ๋ง๋ ๋์ ์ค์ง ์ ๋ํ ํจ์ ์์ฑ์ด๋ค.
e. stickyHeaderIndices{[0]}
: FlatList ๋ด๋ถ์ Header๊ฐ ์คํฌ๋กค์ ์์ง์ฌ ์ ๋ณด์ด์ง ์๊ณ , ํ๋ฉด ์๋จ์ ๊ณ ์ ๋๋๋ก ํ๋ ์์ฑ์ด๋ค.
์ธ์ ๊ฐ์ผ๋ก ๋ฐฐ์ด์ ๋ฃ๋๋ฐ, ๋งจ ์๋จ ํ๊ทธ๋ฅผ index 0์ผ๋ก ๊ฐ์ฃผํ์ฌ column ๋ฐฉํฅ์ผ๋ก ํ๊ทธ ํ๋์ฉ ์ธ๋ฑ์ฑ ๋ฒํธ๊ฐ ์ฃผ์ด์ง๋ค.
๋ง์ฝ [1]์ด๋ผ๊ณ ์ธ์๋ฅผ ๋ฃ์ผ๋ฉด ๋งจ ์๋จ ํ๊ทธ์ ๊ทธ ๋ค์ ํ๊ทธ๊น์ง ๊ณ ์ ๋๋ค.
f. renderItem
: ScrollView์ Map ๊ณผ ๊ฐ์ ๋ ์์ด๋ค.
์ฌ๊ธฐ์๋ ํ๊ทธ ๊ฐ๋ ์ฑ์ ์ํด ๋ด์ฉ์ ํจ์๋ก ๋ง๋ค์ด ๋ฐ๋ก ๋บ๋ค.
const renderItem = ({item}) => (
<View>
<Profile
uri={item.uri}
name={item.name}
introduction={item.introduction}
isMe = {false}
/>
</View>)
renderItem์ ๋ด์ฉ์ด๊ณ ์ธ์๋ก ๊ฐ์ฒด๋ฅผ ๋ฃ์ผ๋ฉด ํจ์ ๋ด์ฉ ๋ถ๋ถ์์ ๊ฐ์ฒด์ ๋ฉค๋ฒ๋ค์ ๊บผ๋ด์ ์ผ์ ์ฒ๋ฆฌ ํ๋ค.
g. ListHeaderComponent์ ListFooterComponent
ํด๋น ๊ธฐ๋ฅ์ ์ด๋ค ํ๊ทธ ํน์ View๋ฅผ ๋ฃ์ผ๋ฉด Header์ ๋ฃ์ ๊ฐ์ ๋งจ ์๋จ, Footer์ ๋ฃ์ ๊ฐ์ ๋งจ ํ๋จ์ ์์นํ๋ค.
h. showVerticalScrollIndicator
๋งจ ์ค๋ฅธ์ชฝ์ ํ๋ฉด ์คํฌ๋กค ์ ์๊ธฐ๋ bar๋ฅผ ํ๋ฉด์ ๋ํ๋ผ ๊ฒ์ด๋ ์๋๋๋ฅผ boolean ๊ฐ์ผ๋ก ๋ํ๋ธ๋ค.
(2) ์ฝ๋ ๋ง๋ ํ๋ฆ
a. ํ๋ซ๋ฆฌ์คํธ์ data ๋ฃ๊ณ , ์คํฌ๋กค ๋๋๋ก ํ๊ธฐ
return (
<View style={styles.container}>
<FlatList
data={isOpened ? friendProfiles : []}
contentContainerStyle = {{paddingHorizontal: 15,}}
keyExtractor={(_, index) => index}
ItemSeparatorComponent={ItemSeparatorComponent}
stickyHeaderIndices={[0]}
renderItem={renderItem}
ListHeaderComponent={ListHeaderComponent}
ListFooterComponent={ListFooterComponent}
showsVerticalScrollIndicator ={false}
>
</FlatList>
<TabBar selectedTabIdx = {selectedTabIdx} setSelectedTabIdx = {setSelectedTabIdx}/>
</View>
)
View ๋ด์ฉ ๋ค ์ญ์ ํ๊ณ FlatList๋ก ์ฑ์.
Footer๋ FlatList ๋ฐ์ ๋นผ๋ . (์ด๊ฑด ๊ณ ์ ํ๋ ์์ฑ ์๋๋ด.)
์๋ FriendList ์ ์ฐ๊ณ , ๊ทธ ์์ ์ ์๋ ํ๊ทธ๋ค์ ํ๋์ View๋ก ๋ฌถ์ด์ ListHeaderComponent์ ์ธ์๋ก ๋ฃ์.
const ListHeaderComponent = () => (
<View style={{backgroundColor: "white"}}>
<Header />
<Margin height = {10}/>
<Profile
uri={myProfile.uri}
name={myProfile.name}
introduction={myProfile.introduction}
isMe = {true}
/>
<Margin height={15}/>
<Division/>
<Margin height={12}/>
<FriendSection
friendProfileLen = {friendProfiles.length}
onPressArrow={onPressArrow}
isOpened = {isOpened}
/>
<Margin height={13}/>
</View>)
** ์ฐธ๊ณ () => {return ํํ๋ฌธ}์ () => ํํ๋ฌธ๊ณผ ๊ฐ๋ค.
์์ ๊ฒฝ์ฐ๋ ()๋ก ๋ชจ๋ ๋ฌถ์ด์ ํ์์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ๊ฒ์ด๋ค.
b. Header,Footer ๋ถ๋ถ๋ ๋ณด์ด๋๋ก ๋ง๋ค๊ธฐ
itemseperator, HeadeComponent, footerComponent์ ์ธ์๋ก View ๋ฌถ์ ๋ฃ์ด์ ๋ณด์ด๊ฒ ํจ.
c. Header์ Footer๋ ์คํฌ๋กค์ ์ํฅ ๋ฐ์ง ์๊ณ ๊ณ ์ ๋๋๋ก ๋ง๋ค๊ธฐ
d. ํ ๊ธ ๋ฒํผ ๋๋๋ก ๋ง๋ค๊ธฐ
ํ์ดํ๋ ์ ์์ง์ด๋๊น ๊ฑด๋๋ฆด ๊ฒ ์๊ณ ,
data={isOpened ? friendProfiles : []}
ํ์ดํ ์์ง์ด๊ฒ ํ๋ state๋ฅผ ์ด์ฉํด ํ์ดํ ์ด๋ ค ์์ผ๋ฉด data์ ์ธ์ ์ ์์ ์ผ๋ก ๋ค์ด๊ฐ๊ฒ, ์๋๋ฉด ๋น ๋ฐฐ์ด์ ์ค๋ค.
e. ๋ด ํ๋กํ๊ณผ ์น๊ตฌ ํ๋กํ ์ฌ์ง ํฌ๊ธฐ, ๊ธ์ ํฌ๊ธฐ ์๋ก ๋ค๋ฅด๊ฒ ์กฐ์
export default ({uri, name, introduction, isMe}) => {
const size = isMe ? 50 : 40;
return (
<View style={{flexDirection: "row", }}>
<Image source={{uri: uri}} style={{width: size, height: size, borderRadius: size*0.4}}/>
<View style={{justifyContent: "center", marginLeft: 10 }}>
<Text style= {{fontWeight: isMe? "bold" : undefined, fontSize: isMe ? 16 :14}}>{name}</Text>
{!!introduction && (
<View>
<Margin height= {isMe ? 6 : 2}/>
<Text style = {{fontSize: isMe ? 12 : 11 , color: "grey"}}>{introduction}</Text>
</View>
)}
</View>
</View>
)
}
Profile.js ์์ ์ผํญ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ค. ์ผ๋จ isMe๋ ์์ฑ์ ๋ง๋ค์ด ๋ง์ฝ ๋ด ํ๋กํ์ด๋ฉด true, ์๋๋ฉด false๋ก ๊ตฌ๋ถํ๋ค.
f. ๋ง์ฝ ์น๊ตฌ๊ฐ ์๊ฐ๊ธ ์ ์ฐ๋ฉด ์ด๋ฆ์ด ๊ฐ์ด๋ฐ ์ค๋๋ก ๋ง๋ค๊ธฐ
<View style={{justifyContent: "center", marginLeft: 10 }}>
<Text style= {{fontWeight: isMe? "bold" : undefined, fontSize: isMe ? 16 :14}}>{name}</Text>
{!!introduction && (
<View>
<Margin height= {isMe ? 6 : 2}/>
<Text style = {{fontSize: isMe ? 12 : 11 , color: "grey"}}>{introduction}</Text>
</View>
)}
์ผ๋จ ๋ฉ์ธ ์ถ์ด colume์ธ ์ํฉ์์ ๋ฐ๋ ์ถ์ธ row์ ๊ฐ ์ ๋ ฌ์ center๋ก ํด์ค๋ค. (ํผ์ ๋ฐ์ ์์ผ๋ฉด ์ค์์ ์ค๊ฒ)
!!introduction์ผ๋ก ์จ์ค ์ด์ ๋ ๊ทธ๋ฅ introduction๋ง ์ผ์ผ๋ฉด, JS๊ฐ ์กฐ๊ฑด๋ฌธ์ผ๋ก ์ธ์ํ์ง ๋ชปํ๊ณ introduction์ ๊ฐ์ ๊ทธ๋ฅ ์ถ๋ ฅํด๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ด๋ค. ({A} ๋ A๋ ๋ณ์์ ๊ฐ์ ๋ฐํ) ์ด์ค ๋ถ์ ์ ํตํด ํด๋น ๋ณ์๊ฐ boolean์ผ๋ก ์ฌ์ฉ๋ ๊ฒ์์ ์๋ ค์ค๋ค.
3. ์ค์ค๋ก ํด๋ณด๊ธฐ
(1) footer๋ฅผ flatList ๋ฐ๊นฅ์ผ๋ก ๋นผ๋ ๊ฒ์์ ๋ฌธ์ ์๊ฒผ์.
์ ์ฒด ํ๋ฉด์ flex: 1 ์ ๋ฃ์ด์คฌ์ ๋๋
๋ฐ์ ํ๋จ๋ฐ๋ฅผ flatlist ๋ฐ๊นฅ์ผ๋ก ๋นผ๋ฉด ์ ๋ณด์๋๋ฐ
flex:1 ๋ฃ์ด์ฃผ๋ ๋ณด์.