我需要帮助。我在 React Native 中制作了一个聊天应用程序,但是当我向上滚动浏览一些聊天时遇到了一些问题,然后当我点击 TextInput 时,我的 FlatList 或 VirtualizedList 从索引 0 开始,这是我不想要的,我所期望的就像在WhatsApp中一样,在滚动了一些距离之后,当我们按下输入字段时它不会滚动到底部而是静止不动
分享这方面的视频。 https://youtu.be/DvrdTFWpREo
我使用 REST 国家 API https://restcountries.eu/重现了这里的场景
我没有改变任何状态,因此我认为它不是重新渲染。
要点链接:https ://gist.github.com/sultanularefin/7eb11e5d278020bffd1d51ac58efd664
import React, {
useState,
useRef,
useEffect,
} from 'react';
import {
Dimensions,
Text,
View,
FlatList,
TouchableOpacity,
TextInput,
StyleSheet,
Keyboard,
VirtualizedList,
ListRenderItem,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import MTI from 'react-native-vector-icons/MaterialCommunityIcons';
export interface Props {
}
export interface Currency {
code: string;
name: string;
symbol: string;
}
export interface Language {
iso639_1: string;
iso639_2: string;
name: string;
nativeName: string;
}
export interface Translations {
de: string;
es: string;
fr: string;
ja: string;
it: string;
br: string;
pt: string;
nl: string;
hr: string;
fa: string;
}
export interface RegionalBloc {
acronym: string;
name: string;
otherAcronyms: string[];
otherNames: string[];
}
export interface RootObject {
name: string;
topLevelDomain: string[];
alpha2Code: string;
alpha3Code: string;
callingCodes: string[];
capital: string;
altSpellings: string[];
region: string;
subregion: string;
population: number;
latlng: number[];
demonym: string;
area?: number;
gini?: number;
timezones: string[];
borders: string[];
nativeName: string;
numericCode: string;
currencies: Currency[];
languages: Language[];
translations: Translations;
flag: string;
regionalBlocs: RegionalBloc[];
cioc: string;
key: string;
}
const genericHeight = 50;
const itemLayoutHeights: Array<number> = [];
const App2: React.FC<Props> = ({}) => {
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [allCountryInfo, setAllCountryInfo] = useState<Array<RootObject>>();
const [messageInputState, setMessageInputState] = useState('');
const partnerChatsVLLRef = useRef<FlatList>(null);
const messageInputRef = useRef(null);
const onChangeTextLoggerInput = (inputValue:string) => {
console.log(` inputValue ==> ${inputValue}`);
setMessageInputState(inputValue);
};
useEffect(() => {
const getData = ()=> {
const url = 'https://restcountries.eu/rest/v2/';
fetch(url)
.then(res => res.json())
.then(
(result) => {
setError(null);
setIsLoaded(true);
const allResult = result.map((oneInterest: RootObject) => ({
...oneInterest,
key: oneInterest.nativeName,
}
)
);
setAllCountryInfo(allResult);
},
(error3) => {
setIsLoaded(true);
setError(error3);
setAllCountryInfo([]);
}
).catch((error2) => {
console.log('error2: ', error2);
setIsLoaded(true);
setAllCountryInfo([]);
});
};
getData();
}, []);
const renderItemGetItemLayOut: ListRenderItem<RootObject> = ({
item,
index,
separators }) => {
return (
<View
style={{
height: genericHeight,
width: deviceWidth,
backgroundColor: '#f9c2ff',
borderWidth: 1,
paddingStart: 10,
}}
onLayout={ (object) =>{
itemLayoutHeights[index] = object.nativeEvent.layout.height;
}}
>
<Text
style={{
fontSize: 32,
color: 'black',
width: deviceWidth,
textAlign: 'left',
}}>
{index}: {item.name}
</Text>
</View>
);
};
// NHS F.... NHS Fianl..
console.log("allCountryInfo.length: ", allCountryInfo?.length);
return (
<View style={{
flex: 10,
flexDirection: 'column',
}}>
<View style={{
flex: 9,
paddingVertical: 8,
justifyContent: "flex-start",
}}
>
<FlatList
style={{
}}
ref= {partnerChatsVLLRef}
data= {allCountryInfo}
renderItem= {renderItemGetItemLayOut}
keyExtractor= {(item) => item.key}
inverted={true}
getItemLayout = {(data, index) => ({
length: (itemLayoutHeights[index] === undefined)
? 100
: itemLayoutHeights[index],
offset: itemLayoutHeights.slice(0, index).reduce((a, c) => a + c, 0),
index,
}
)}
/>
</View>
<View style={{
flexDirection: 'column',
flex: 1,
paddingBottom: 20,
width: deviceWidth,
}}
>
<View style={partnerChatsStyle.messageinputcontainerElse}>
<TextInput
style={partnerChatsStyle.messageinputElse}
placeholder="Enter Message"
ref={messageInputRef}
onChangeText={
(text) => onChangeTextLoggerInput(text)
}
onPressIn={
(e) => {
console.log("event for onPressIn: ", e.target.viewConfig.uiViewClassName);
// e.preventDefault();
}
}
onFocus={
(e) =>{
console.log("event for onFocus", e.target.viewConfig.uiViewClassName);
// e.preventDefault();
}
}
/>
<View style={{
flex: 0.15,
flexDirection: 'row',
justifyContent: 'flex-start',
paddingLeft: 7,
}}
>
<TouchableOpacity
onPress={() => console.log("invokeActionSheet()")}
>
<Icon
size={40}
color='black'
name={'ios-attach'}
/>
</TouchableOpacity>
</View>
<View style={{
flex: 0.15,
flexDirection: 'row',
justifyContent: 'flex-start',
paddingLeft: 7,
}}
>
<TouchableOpacity
style={partnerChatsStyle.roundedbackgroudElse}
onPress= { () =>console.log("insertChatAndImagesToServer")}
>
<MTI
size={45}
style={{
color: 'white',
textAlign: 'left',
alignSelf: 'stretch',
fontSize: 40
}}
name={'send-circle'}
/>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
};
const partnerChatsStyle = StyleSheet.create({
messageinputElse: {
flex: 0.7,
textAlign: 'justify',
height: 50,
borderWidth: 1,
borderColor: '#e0e0e0',
borderRadius: 20,
backgroundColor: '#FFFFFF',
paddingLeft: 10,
color: 'black',
},
messageinputcontainerElse: {
flex: 1,
flexDirection: 'row',
height: 50,
backgroundColor: 'transparent',
marginLeft: 10,
},
roundedbackgroudElse: {
height: 40,
width: 40,
justifyContent: 'center',
borderRadius: 70,
backgroundColor: 'black',
},
});
export default App2;