
TextInput에 scrollEnabled={false} 속성을 추가하면 자동으로 스크롤이 된다. 하지만, 키보드가 있는 영역은 가려지게 되어 결국 안보이게 된다.
<ScrollView>
<TextInput
onChangeText={(text) => {
setTitleText(text);
}}
multiline={true}
scrollEnabled={false}
/>
</ScrollView>
ScrollView 대신에 KeyboardAvoidingView를 사용해 해결npm install react-native-keyboard-aware-scroll-view을 하여 이 라이브러리를 설치한 뒤, ScrollView 대신에 KeyboardAwareScrollView을 사용한다. 그러면 문자가 가려지지 않는다.
<KeyboardAwareScrollView style={{ flex: 1 }}>
<TextInput
onChangeText={(text) => {
setTitleText(text);
}}
multiline={true}
scrollEnabled={false}
/>
</KeyboardAwareScrollView>
KeyboardAvoidingView로 전체를 감싸고, attribute로 behavior="padding"을 넣어줘 해결KeyboardAvoidingView에 속성으로 behavior="padding"을 추가하면, 키보드에 의해 문자가 가려지지 않는다. 속성을 추가하지 않으면 문자가 가려지니 주의!
<KeyboardAvoidingView behavior="padding" style={{ flex: 1 }}>
<ScrollView>
<TextInput
onChangeText={(text) => {
setTitleText(text);
}}
multiline={true}
scrollEnabled={false}
/>
</ScrollView>
<KeyboardAvoidingView>
위의 방법에서 나는 2번으로 진행했다. 2번으로 하면 그냥 ScrollView 아래에 버튼들을 추가하면 된다.KeyboardAvoidingView에 behavior="padding"을 추가하면, 키보드가 나올 때 KeyboardAvoidingView 내부에 있는 모든 컴포넌트들을 다 위로 올려주기 때문!
근데 주의할 점이KeyboardAvoidingView의 속성으로 keyboardVerticalOffset={Platform.OS === "ios" ? 90 : 0}을 추가해줘야한다. IOS에서는 조금 더 Offset을 줘야 '버튼 바'가 가려지지 않는다. 하지만, Android에서 Offset을 주면 키보드를 열지 않았을 때, '버튼 바'만 붕 뜨는 일이 발생한다.
<KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={Platform.OS === "ios" ? 90 : 0}
style={{ flex: 1 }}>
<ScrollView>
<TextInput
onChangeText={(text) => {
setTitleText(text);
}}
multiline={true}
scrollEnabled={false}
/>
</ScrollView>
<View style={styles.floatingButtonContainer}>
<Button title="Button1" />
<Button title="Button2" />
</View>
<KeyboardAvoidingView>
첫 번째 문제는 ScrollView에 keyboardDismissMode="on-drag" 속성을 추가하면 해결할 수 있다. 이는 드레그를 해서 키보드를 내릴 수 있게 해준다.
두 번째 문제가 발생하는 이유는 ScrollView 내부에서 버튼을 누르려면 일단 키보드가 없어진 다음에 버튼이 눌려야했기 때문이며,이로 인해 동작이 부자연스러웠던 것이다. 따라서 키보드가 켜진 상태에서도 버튼을 누를 수 있게 해야한다.ScrollView에 keyboardShouldPersistTaps="always" 를 해주면, 키보드가 있는 상태에서도 버튼을 누를 수 있다.
<KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={Platform.OS === "ios" ? 90 : 0}
style={{ flex: 1 }}>
<ScrollView
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="always"
>
<TextInput
onChangeText={(text) => {
setTitleText(text);
}}
multiline={true}
scrollEnabled={false}
/>
</ScrollView>
<View style={styles.floatingButtonContainer}>
<Button title="Button1" />
<Button title="Button2" />
</View>
<KeyboardAvoidingView>

여러 테스트를 하던 중, 위 문제가 발생했다. TextInput을 입력할 때 항상 가장 끝, 그러니까 가장 우측 하단에 문자를 입력한 다음에 또 문자를 입력하면 갑자기 위로 스크롤 됐다. 우측 하단에 문자를 입력할 때만 이 문제가 나오는 것을 보고 TextInput의 크기와 연관이 있다고 생각했다. 뚜렷한 해결법을 찾지 못하다가 Handling TextInput in react native라는 제목을 블로그를 발견했고, 위 문제를 해결할 수 있었다.
결론은 TextInput의 크기가 변했을 시, 크기를 늘려주면 된다. 이를 위해 TextInput의 속성으로
style={[styles.textBody, { height: bodyTextHeight }]}
onContentSizeChange={
//+100 정도 해줘야 TextInput 젤 위로 다시 올라가는 현상을 방지해줌
(event) => setBodyTextHeight(event.nativeEvent.contentSize.height + 100)
}
을 추가했다.
onContentSizeChange를 통해 TextInput의 크기 변화가 있을 때 높이를 받아오고, const [bodyTextHeight, setBodyTextHeight] = useState(0);를 설정하여 이 State로 높이를 받아오게 했다. 그리고 style에 변화된 높이를 반영해주어 높이 변화에 맞춰 높이 값을 변경해줬다. 또한 넉넉하게 100 정도 더 크게 해줬는데, 그냥 event.nativeEvent.contentSize.height로 높이를 설정해주면 제일 위로 올라가는 현상이 다시 나오기 때문에 Offset으로 100만큼 더 추가했다.
<KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={Platform.OS === "ios" ? 90 : 0}
style={{ flex: 1 }}
>
<ScrollView
enableResetScrollToCoords={false}
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="always"
>
<TextInput
style={[styles.textBody, { height: bodyTextHeight }]}
placeholder="Body"
multiline={true}
onChangeText={(text) => {
setBodyText(text);
}}
onContentSizeChange={
//+100 정도 해줘야 TextInput 젤 위로 다시 올라가는 현상을 방지해줌
(event) =>
setBodyTextHeight(event.nativeEvent.contentSize.height + 100)
}
scrollEnabled={false}
/>
</ScrollView>
<View style={styles.floatingButtonContainer}>
<Button title="Button1" />
<Button title="Button2" />
</View>
</KeyboardAvoidingView>
선생님의 글이 저를 살렸습니다.. 감사합니다 :)