반응형
리액트 네이티브 채팅방 구현하기
요즘 리액트 네이티브를 활용해서 채팅 기능을 구현하고 있다.
그 중에서도 Android와는 달리 iOS에서 키보드가 입력창을 가리는 현상 때문에 고생이 많았다. 그 문제를 해결하던 과정을 기록하였다.
KeyboardAvoidingView
이 이슈에 대해 검색을 해보면 먼저 이 KeyboardAvoidingView
가 가장 먼저 결과로 나올 것이다. 그래서 처음에는 이 View를 활용해서 구현했다. 하지만, 문제점이 있었다. 입력창은 키보드 위로 잘 밀려올라가지만, 채팅 내용은 그대로 있다는 점이다. 다시 원래 보고 있던 채팅을 보려면 스크롤을 다시 해야한다는 단점이 느껴져서 해결하고자 노력했다.
import React from 'react';
import { KeyboardAvoidingView, Platform, StyleSheet } from 'react-native';
import { useHeaderHeight } from '@react-navigation/elements';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
type AvoidingViewProps = {
children: React.ReactNode;
};
const TextInputAvoidingView = ({ children }: AvoidingViewProps) => {
const headerHeight = useHeaderHeight();
const inset = useSafeAreaInsets();
return Platform.OS === 'ios' ? (
<KeyboardAvoidingView
style={[styles.wrapper, { marginBottom: inset.bottom }]}
behavior="padding"
keyboardVerticalOffset={headerHeight}>
{children}
</KeyboardAvoidingView>
) : (
<>{children}</>
);
};
export default TextInputAvoidingView;
const styles = StyleSheet.create({
wrapper: {
flex: 1,
},
});
그래서 다른 오픈소스 Chat UI에서는 어떻게 해결하는지 파악해봤다.
해결의 실마리는 링크에서 찾을 수 있었다.
KeyboardAccessoryView라는 커스텀 컴포넌트로 감싸서 해결하기에 해당 레포로 이동해보니 리액트 네이티브 레포의 풀리퀘스트로 안내하였다. 링크
결론: ScrollView or FlatList + InputAccessoryView
해당 풀리퀘스트로 이동해보면, 아래와 같이 리액트 네이티브에서 제공하는 View만으로 해결이 가능하게 업데이트가 되었다는 이야기이다.
export const ChatPage = ({
flatListProps,
textInputProps
}: Props): React.ReactElement => (
<>
<FlatList
{...flatListProps}
keyboardDismissMode="interactive"
automaticallyAdjustContentInsets={false}
contentInsetAdjustmentBehavior="never"
maintainVisibleContentPosition={{ minIndexForVisible: 0, autoscrollToTopThreshold: 100 }}
automaticallyAdjustKeyboardInsets={true}
/>
<InputAccessoryView backgroundColor={colors.white}>
<ChatInput {...textInputProps} />
</InputAccessoryView>
</>
);
iOS의 경우 Input 컴포넌트를 InputAccessoryView
로 감싸주면, 키보드의 위쪽에 붙어있는 View를 구현할 수 있었고, 안드로이드의 경우 자동적으로 적용이 되었다. 따라서 최종적인 코드는 아래와 같이 OS 별로 구별해주어야 한다.
<View style={[styles.ChatRoomContainer, { marginBottom: inset.bottom }]}>
<>
<FlatList
contentContainerStyle={styles.contentContainer}
data={messages}
renderItem={renderItem}
automaticallyAdjustContentInsets={false}
inverted={true}
keyboardDismissMode="interactive"
keyboardShouldPersistTaps="handled"
contentInsetAdjustmentBehavior="never"
maintainVisibleContentPosition={{
minIndexForVisible: 0,
autoscrollToTopThreshold: 80,
}}
automaticallyAdjustKeyboardInsets={true}
/>
{Platform.OS === 'ios' ? (
<InputAccessoryView>
<InputToolbar />
</InputAccessoryView>
) : (
<InputToolbar />
)}
</>
</View>
이제는 머리 아프게 KeyboardAvoidingView 혹은 써드파티 라이브러리를 사용하지 않아도 된다!
결과물
iOS
Android
반응형
'개발 > 오늘 배운 지식' 카테고리의 다른 글
[FastAPI/Python] FastAPI 프로젝트 배포하기 (0) | 2022.08.18 |
---|---|
[FastAPI/Python] API를 비동기적으로 테스트하기(with pytest, HTTPX) (0) | 2022.08.13 |
[FastAPI/Python] 양방향 통신을 위한 웹소켓 in FastAPI (0) | 2022.08.12 |
[FastAPI/Python] FastAPI에서의 인증과 보안 (0) | 2022.08.11 |
[FastAPI/Python] FastAPI를 Tortoise ORM과 MongoDB와 연동하기 (2) | 2022.08.09 |