text in flatlist going off screen react native - react-native

I tried basically every answer from this question and nothing seems to work: React native text going off my screen, refusing to wrap. What to do?
I am facing the same issue where my text goes off-screen and seems to be operating at a width of about 130% or so.
Here is the screen I render the list:
<View style={styles.container}>
<FlatList
data={messagePreviewData}
renderItem={({ item }) =>
<ChatPreview
readMessage={item.readMessage}
imgUri={item.imgUri}
username={item.username}
time={item.time}
message={item.message}
/>
}
keyExtractor={(item, index) => item.username + index}
/>
</View>
const styles = StyleSheet.create({
container: {
backgroundColor: colors.neutralOne,
flex: 1,
}
});
And here is the ChatPreview component, where the message text goes off-screen:
const ChatPreview = (props: ChatPreviewProps) => {
const { readMessage, imgUri, username, time, message } = props;
return (
<View style={styles.container}>
<View style={styles.leftContainer}>
<View style={styles.badgeAvatarContainer}>
<Avatar
rounded
source={{ uri: imgUri }}
size={scaledSize(50)}
/>
</View>
<View style={styles.usernameMessageContainer}>
<Text style={styles.username}>{username}</Text>
<Text style={styles.messagePreview} numberOfLines={2} ellipsizeMode='tail'>
{message} // this is what's going off screen
</Text>
</View>
</View>
<Text style={styles.time}>{time}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 10,
},
leftContainer: {
flexDirection: 'row'
},
badgeAvatarContainer: {
flexDirection: 'row',
alignItems: 'center',
marginRight: 10
},
usernameMessageContainer: {
// I have tried putting many things here and nothing seems to work
},
username: {
color: colors.neutralEight,
fontFamily: fonts.bodyTwoBold.fontFamily,
fontSize: fonts.bodyTwoBold.fontSize,
lineHeight: fonts.bodyTwoBold.lineHeight,
},
messagePreview: {
color: colors.neutralFour,
fontFamily: fonts.captionOne.fontFamily,
fontSize: fonts.captionOne.fontSize,
lineHeight: fonts.captionOne.lineHeight,
},
time: {
color: colors.neutralFour,
fontFamily: fonts.captionTwo.fontFamily,
fontSize: fonts.captionTwo.fontSize,
lineHeight: fonts.captionTwo.lineHeight
}
});

It might be worth setting flex:1 from parent down to the child where the content is going off screen. I've had issues where I've forgotten to do it and it's been messed up.
Essentially you could add flex:1 to every style in ChatPreview to try it out, It won't look super nice probably but you should see if the issue is fixed I believe and tweak it from there.

coincidently i was doing a similar thing yesterday. So as you are using flex-direction row , thus , the text (which tries to get all the width given to it, by default 100%) goes out of screen as now 100% is what you said 130%. Now to restrict it, we just need to restrict its width. So set width on the text, maybe only 60% or 70% and it will work fine.

Related

React Native Image resizeMode adding additional vertical space for scaling

I have the following component that has some text and an image.
const EmptyListPlaceholder = () => {
return (
<View style={styles.container}>
<Text style={[globalStyles.headerSection, styles.title]}>Nothing here yet...</Text>
<Text style={[globalStyles.bodySmall, styles.descText]}>Ideas will show here once liked or favorited.</Text>
<Image
source={require('../../assets/images/Illustration_Empty-State.png')}
resizeMode={'contain'}
style={{ width: '100%', backgroundColor: 'red' }}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
},
descText: {
fontFamily: Metropolis[500].Regular,
},
title: {
fontFamily: Metropolis[700].Regular,
margin: 4,
},
});
Why does resizeMode={'contain'} add additional space above and below the image? You can see this from the red background. I would expect the top of the image to be flush with the bottom of the description text.

When stickyHeaderIndices is used, style of component changes

I've searched common problems and how to use stickyHeaderIndices and so on. But stuck with one point, and I didn't even find why this occurs, so couldn't search on the internet.
Everything works fine on web, but not on my phone when I use sticky.
My Scroll View Structure:
<ScrollView stickyHeaderIndices={[0]} style={styles.layout}>
<View style={styles.topBar}>
<Text style={styles.title}>Messages</Text>
<View style={styles.notificationIcon}>
<Text style={styles.notificationIconTxt}>{notificationCount}</Text>
</View>
</View>
<ChatItem pairingCategory={'Name'} />
</ScrollView>
View that I want to stick on top:
If I use the structure above, it sticks on top but style of the component changes (as in the picture below), I want that bubble to stay next to text.
Here's my styles:
const styles = StyleSheet.create({
layout: {
flex: 1,
backgroundColor: colors.lightBg
},
topBar: {
backgroundColor: colors.lightBg,
paddingVertical: 15,
paddingLeft: 24,
flexDirection: 'row',
flexWrap: 'nowrap',
alignItems: 'center',
},
title: {
fontSize: 32,
marginRight: 8,
},
notificationIcon: {
borderRadius: 15,
justifyContent: 'center',
alignItems: 'center',
width: 30,
height: 30,
backgroundColor: colors.mainBg,
padding: 5
},
notificationIconTxt: {
color: 'white',
fontWeight: "700"
}
})
Whenever I delete stickyHeaderIndices, topBar view seems the way I want, but not sticks to top.
Why it happens, and what can I do to solve it?
Solved!
I still don't know, what was the reason for it, but created new component called ChatListTopBar then wrapped my first children View.
function ChatListTopBar({notificationCount}) {
return (
<View style={styles.topBar}>
<Text lineBreakMode='false' style={styles.title}>Mesajlar</Text>
<View style={styles.notificationIcon}>
<Text style={styles.notificationIconTxt}>15</Text>
</View>
</View>
)
}
//ScrollView section seems so
<ScrollView stickyHeaderIndices={[0]} style={styles.layout}>
<ChatListTopBar notificationCount={notificationCount} />
<ChatItem pairingCategory={'Name'} />
</ScrollView>
Replacing like so, just fixed the issue!
wrap your View which you are trying to stick with <></>

The style of the application changes when I wrap components in a ScrollView

I'm getting acquainted with react-native and faced the following problem: when I add a ScrollView and put content in it, the style of the application changes. How can this issue be resolved?
Before adding the ScrollView:
After adding the ScrollView:
function Weather({ temp, city, condition, daily, hourly }) {
return (
<LinearGradient
colors={weatherOptions[condition].gradient}
style={styles.container}
>
<StatusBar style="light" />
<ScrollView>
<View style={styles.topContainer}>
<MaterialCommunityIcons
name={weatherOptions[condition].iconName}
size={96}
color="#fff"
/>
<Text style={styles.text}>{city}</Text>
<Text style={styles.text}>{temp}℃</Text>
</View>
<View style={styles.bottomContainer}>
<WeatherDaily daily={daily} />
<WeatherHourly hourly={hourly} />
<DetailedDailyForecast />
</View>
</ScrollView>
</LinearGradient>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
text: {
fontSize: 28,
color: "white",
},
image: {
width: 100,
height: 100,
},
topContainer: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
bottomContainer: {
flex: 1,
},
});
From the docs:
Keep in mind that ScrollViews must have a bounded height in order to work, since they contain unbounded-height children into a bounded container (via a scroll interaction). In order to bound the height of a ScrollView, either set the height of the view directly (discouraged) or make sure all parent views have bounded height. Forgetting to transfer {flex: 1} down the view stack can lead to errors here, which the element inspector makes quick to debug.

React Native TouchableWithoutFeedback on view with position absolute

I have a modal that I want show when the user clicks a i button.
The modal envelops the entire screen, by setting the position to 'absolute'. This works fine, but when the user clicks somewhere on the screen, it should disappear again.
My TouchAbleWithoutFeedback however, does not register a press. It appears to be having something to do with the position being absolute but I can't put my finger on it.
Also, the clickable elements underneath the modal are still interactable, even though the modal is displayed on top of those elements.
Here is my code:
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
render()
{
return (<View>
<View style={styles.container}>
<OtherElements/>
</View>
<MainScreenInfoModal showModal={this.state.showInfoModal} />
</View>);
}
const MainScreenInfoModal = ({showModal}) =>
{
if (showModal)
{
return <TouchableWithoutFeedback style={{zIndex: 10}} width={window.width} height={window.height} onPress={() => {console.log('press!')}}>
<View style={styles.infoModal} >
<SvgXml width={300} height={300} xml={mainscreenInfomodal} style={{
alignSelf: 'center',
marginTop: window.height * .45
}}/>
</View>
</TouchableWithoutFeedback>
}
return null;
}
const styles = StyleSheet.create({
container:
{
fontSize: 26,
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
padding: 13,
fontWeight: "bold",
},
{...} ,
infoModal:
{
position: 'absolute',
bottom: 0,
width: window.width,
height: window.height,
backgroundColor: 'rgba(255,255,255,0.7)',
zIndex: 10
}});
try react-native-modalize library, it saved me alot of time and nerves developing modals

Know which element was touched with React Native's PanResponder?

Im making a drag and drop with the PanResponder but I only want part of a component to be the 'target' which initiates the drag. Many elements are contained within a ScrollView, and dragging on the elements outside of the 'target' should scroll as usual.
const Dragger = () => {
return (
<View {...panResponder.panHandlers}>
<View style={{ flexDirection: 'row' }}>
<Text>Drag me</Text>
<Text>Im not draggable</Text>
</View>
<View style={{ flexDirection: 'row' }}>
<Text>Drag me</Text>
<Text>Im not draggable</Text>
</View>
</View>
)
}
const Parent = () => {
return(
<ScrollView>
<Text>Stuff</Text>
<Dragger />
<Text>Stuff</Text>
<ScrollView/>
)
}
Can this be done or do I need to attach multiple panHandlers to each <Text>Drag me</Text>?
From the docs I see there is a nativeEvent.target which returns "The node id of the element receiving the touch event", however it's just a number so Im not sure how to use it?
Would I need to find out the node IDs of the <Text>Drag me</Text> elements and see if the number that came back is in that list?
UPDATE: Here is a more visual demo of what Im trying to do:
https://snack.expo.io/#jamesweblondon/rude-pretzel
I need PanResponder drag events on the grey boxes, but not on the text inputs:
import React from "react";
import { StyleSheet, Text, View, TextInput } from "react-native";
const items = new Array(50).fill(0).map((item, index) => {
return {
id: index,
backgroundColor: `rgb(${Math.floor(Math.random() * 255)}, ${
index * 5
}, ${132})`,
};
});
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
item: {
display: "flex",
flexDirection: "row",
height: 200,
width: "100%",
justifyContent: "space-around",
alignItems: "center",
},
input: {
color: "white",
fontSize: 20,
height: "100%",
flex: 1,
},
handle: {
display: "flex",
backgroundColor: "grey",
height: "80%",
width: 100,
marginHorizontal: 20,
},
});
export default function App() {
return (
<View style={styles.container}>
{items.map((item) => {
return (
<View
style={[styles.item, { backgroundColor: item.backgroundColor }]}
>
<View style={styles.handle} />
<TextInput style={styles.input} defaultValue={item.id} />
</View>
);
})}
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
You started your question with some snippets that I couldn't find in the link you posted, so I started from that and created a fork.
So in order to get the PanResponder drag events on the grey boxes, but not on the text inputs you should do like this on your item component:
<View style={[styles.item, { backgroundColor: item.backgroundColor }]} >
<View style={styles.handle} {...panResponder.panHandlers} />
<TextInput style={styles.input}>{item.id}</TextInput>
</View>
For the PanResponder i used the default config from https://reactnative.dev/docs/panresponder#example
Here's an update on your code to try it.
Hope this helps! Tell me if this isn't working for you.