react-native-gifted-chat
react-native-gifted-chat copied to clipboard
Input Accessory And Keyboard Behavior Like Messenger App
Hi guys!
CAN BE DONE?
Can GiftedChat do the same input/keyboard effect as the Messenger app?
The keyboard will be dismiss when user click Gif/Image icon in the accessory, and will come back when user focus text input!
I tried to research about this, and I found: KeyboardAccessoryView
component, develop by Wix. But it has problem in Android, I created an issue here, haven’t fixed yet: https://github.com/wix/react-native-ui-lib/issues/2063
https://user-images.githubusercontent.com/33916400/179034560-04211fa3-c1a5-4ea8-b936-147113acbc73.MOV
Same problem
You can try lib: https://github.com/thomasgazzoni/react-native-keyboard-area for android. You change the SoftInput mode to ADJUST_NOTHING only for the pages, example:
import { RNKeyboard, SoftInputMode } from 'react-native-keyboard-area';
componentDidMount() {
navigation.addListener('blur', this.componentDidExit);
navigation.addListener('focus', this.componentDidEnter);
}
componentDidEnter = () => {
if (Platform.OS === 'android') {
RNKeyboard.setWindowSoftInputMode(SoftInputMode.SOFT_INPUT_ADJUST_NOTHING,);
}
};
componentDidExit = () => {
if (Platform.OS === 'android') {
RNKeyboard.setWindowSoftInputMode(SoftInputMode.SOFT_INPUT_ADJUST_RESIZE);
}
};
componentWillUnmount() {
navigation.removeListener('blur', this.componentDidExit);
navigation.removeListener('focus', this.componentDidEnter);
}
- Add callback when the keyboard height changes (when it show/hide):
RNKeyboard.addKeyboardListener((height) => { keyboardheight = height });
- Add a
View
belowTextInput
and height ofView
change when keyboard height change, example:
<>
<TextInput />
<Animated.View
style={[height: keyboardheight, styles.accessoryView]}
>
{customKeyboard === ComponentID.IMAGE_GALLERY && (
<SelectImageGallery />
)}
</Animated.View>
</>
- For
IOS
, you setisKeyboardInternallyHandled={false}
, and useKeyboard API
listener keyboard height change, example:
useEffect(() => {
if (Platform.OS === 'ios') {
const showSubscription = Keyboard.addListener('keyboardWillShow', (e) => {
keyboardheight = e.endCoordinates.height;
});
const hideSubscription = Keyboard.addListener('keyboardWillHide', (e) => {
keyboardheight = 0;
});
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}
}, []);
- And then you do the same as android
hi @huuthinh95 , can u help my problem? I can not switch keyboard sticker Here is my main view
<View style={{
position: 'absolute',
width: '100%',
height: '100%',
}}>
{renderGiftedChat()}
<KeyboardSpacer
ref={kbRef}
isOpen={customKeyboard == KEYBOARD_SYSTEM}
onChange={(isOpen: boolean, currentHeight: number) => {
console.log('onchange', isOpen, currentHeight)
}}>
{renderAccessory()}
</KeyboardSpacer>
</View>
const renderAccessory = (props) => {
if (customKeyboard == KEYBOARD_EMOJI) return <ChatEmojiKeyboardInput width={width} height={getKbHeight} onSelectEmoji={onSelectEmoji} />
if (customKeyboard == KEYBOARD_MORE) return <ChatMoreKeyboardInput width={width} height={getKbHeight} onSelectedFile={onSelectedFile} onShareContact={onShareContact}/>
if (customKeyboard == KEYBOARD_VOICE) return <ChatVoiceKeyboardInput width={width} height={getKbHeight} onSendVoice={onSendVoice} />
return null
}
Can u tell me what's wrong with my code? Thanks so much
hi @fukemy Your problem on android or IOS. If on android, you need set SoftInput mode to ADJUST_NOTHING.
import { RNKeyboard, SoftInputMode } from 'react-native-keyboard-area';
componentDidMount() {
navigation.addListener('blur', this.componentDidExit);
navigation.addListener('focus', this.componentDidEnter);
}
componentDidEnter = () => {
if (Platform.OS === 'android') {
RNKeyboard.setWindowSoftInputMode(SoftInputMode.SOFT_INPUT_ADJUST_NOTHING,);
}
};
componentDidExit = () => {
if (Platform.OS === 'android') {
RNKeyboard.setWindowSoftInputMode(SoftInputMode.SOFT_INPUT_ADJUST_RESIZE);
}
};
componentWillUnmount() {
navigation.removeListener('blur', this.componentDidExit);
navigation.removeListener('focus', this.componentDidEnter);
}
And you can try your code on IOS.
ya, it's work as expected, im using KeyboardArea it's almost do the job for me. Thanks
@huuthinh95 Thank you! The iOS is smooth but Android still flickers
@000xuandu you can try this code.
import React, { useState, useCallback, useEffect, useRef } from 'react';
import { TextInput, TouchableOpacity, View, Text, Keyboard, Animated, Platform } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
import { RNKeyboard, SoftInputMode, KeyboardArea, KeyboardAreaRef } from 'react-native-keyboard-area';
export function App() {
const [messages, setMessages] = useState([]);
const heightAni = useRef(new Animated.Value(0)).current;
const flag = useRef(false);
const componentDidEnter = () => {
if (Platform.OS === 'android') {
RNKeyboard.setWindowSoftInputMode(SoftInputMode.SOFT_INPUT_ADJUST_NOTHING,);
}
};
const componentDidExit = () => {
if (Platform.OS === 'android') {
RNKeyboard.setWindowSoftInputMode(SoftInputMode.SOFT_INPUT_ADJUST_RESIZE);
}
};
useEffect(() => {
RNKeyboard.addKeyboardListener(keyboardAreaHeightChanged);
return () => {
RNKeyboard.removeKeyboardListener(keyboardAreaHeightChanged)
}
}, [])
const keyboardAreaHeightChanged = useCallback((currentHeight) => {
// Your logic
if (flag.current) {
flag.current = false;
return;
}
Animated.timing(heightAni, {
toValue: currentHeight,
duration: 0,
useNativeDriver: false
}).start();
}, []);
useEffect(() => {
componentDidEnter()
return () => {
componentDidExit()
};
}, [])
useEffect(() => {
setMessages([
{
_id: 1,
text: 'Hello developer',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
])
}, []);
const onSend = useCallback((messages = []) => {
setMessages(previousMessages => GiftedChat.append(previousMessages, messages))
}, []);
const renderInputToolbar = () => {
return (
<Animated.View style={{borderWidth: 1, borderColor: 'red', flex: 1}}>
<TextInput style={{borderWidth: 1, borderColor: 'blue'}} />
<TouchableOpacity onPress={handleChangeMode}>
<Text>Test</Text>
</TouchableOpacity>
</Animated.View>
)
}
const handleChangeMode = () => {
if (heightAni._value === 0) {
Animated.timing(heightAni, {
toValue: 305,//get height of keyboard
duration: 100,
useNativeDriver: false
}).start();
} else {
flag.current = true'''
Keyboard.dismiss()
}
}
return (
<View style={{flex: 1}}>
<GiftedChat
messages={messages}
onSend={messages => onSend(messages)}
user={{
_id: 1,
}}
multiline
renderComposer={renderInputToolbar}
/>
{/* <KeyboardArea
ref={keyboardSpacerRef.current}
isOpen={false}
onChange={keyboardAreaHeightChanged}
>
</KeyboardArea> */}
<Animated.View style={{height: heightAni }}>
<Text>custom content</Text>
</Animated.View>
</View>
)
}
export default App;
hi @huuthinh95 , i want to make the view below keyboard look like bottom sheet, such as the sticker keyboard of Messenger, did u faced this?
@huuthinh95 Android reported this error. Do you have any better suggestions? Thank you
did u used expo?