Last odd flatlist item stretches along screen - react-native

I'm displaying some data items with Flatlist in two columns. But when there is an odd item at the last place, it stretches all along the screen. I don't want that, how can I make it to take only %50 of screen space like even items? Thanks a lot.
CategoryGridTile Component:
return (
<View style={styles.PlaceItem}>
<TouchableCmp onPress={props.onSelect}>
<View>
<View style={{ ...styles.placeRow, ...styles.placeHeader }}>
<ImageBackground
source={{ uri: props.image }}
style={styles.bgImage}
>
<View style={styles.titleContainer}>
<Text style={styles.title} numberOfLines={2}>
{props.title}
</Text>
</View>
</ImageBackground>
</View>
</View>
</TouchableCmp>
</View>
)
}
const styles = StyleSheet.create({
PlaceItem: {
flex: 1,
height: 125,
width: '80%',
backgroundColor: '#f5f5f5',
borderRadius: 5,
overflow: 'hidden',
margin: 6
},
placeRow: {
flexDirection: 'row'
}
})
Screen:
const renderGridItem = itemData => {
return (
<CategoryGridTile
image={itemData.item.image}
title={itemData.item.title}
onSelect={() => {
props.navigation.navigate({
routeName: 'CategoryPlaces',
params: {
categoryId: itemData.item.title,
locationId: locations
}
})
}}
/>
)
}
return (
<FlatList
keyExtractor={(item, index) => item._id}
data={displayedCategories}
renderItem={renderGridItem}
numColumns={2}
/>
)

Changing PlaceItem flex: 1 to flex: 1/2 at CategoryGridTile component solved the problem.

Related

React-Native unable to type in TextInput

I'm learning react-native, currently learning state.
I have a TextInput on my screen:
however, when I try to type in it the text doesn't appear.
My code:
const Login = ({ navigation } : any) => {
const [text, setText] = useState('');
return (
<View style={[styles.container, { flexDirection: "column" }]}>
<View style={{ flex: 1, alignItems:"center", justifyContent:"center" }}>
<Image source={require('../assets/images/help.png') } style={{ width: 40, height: 40 }} />
</View>
<View style={{ flex: 2, backgroundColor: "#5f6364", borderTopRightRadius:20, borderTopLeftRadius:20 }}>
<TextInput style={styles.input} placeholder="Type here to translate!" onChangeText={newText => setText(newText)} defaultValue={text} />
</View>
</View>
)
}
Can someone explain why this is happening?
Try replacing the defaultValue with value or remove it completely

React Native: How can I put a pop-up Modal into flatlist

I've made a flatlist with a few data inside. I want to make a pop-up information for each item in the flatlist. So I tried putting Modal into the renderItem function but when it sets the modal state visible, it will show all of the information in my flatlist. I think it should be setting the modal visible state by id or something like that but I don't know how to do it. Any suggestion?
my renderItem:
function RenderItem({ item }) {
return (
<View>
<Modal
animationType='slide'
transparent={true}
visible={infoModal}>
<View style={styles.informationContainer}>
<View style={styles.informationBox}>
<Text>{item.file.displayName}</Text>
<Button title=' OK ' onPress={() => setInfoModal(false)} />
</View>
</View>
</Modal>
<TouchableOpacity style={styles.listBox} onPress={() => setInfoModal(true)}>
<View>
<Text numberOfLines={1} style={styles.listText}>{item.file.displayName}</Text>
<Text style={{ width: 200, color: 'rgba(0, 0, 0, 0.5)' }}>{item.certificateName}</Text>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
<TouchableOpacity>
<Icon name='search' color='black' size={25} />
</TouchableOpacity>
<Text> </Text>
<TouchableOpacity onPress={() => handleDownload(item)}>
<Icon name='download' color='black' size={25} />
</TouchableOpacity>
<Text> </Text>
</View>
</TouchableOpacity>
</View>
)
}
Instead of setting a simple boolean value about whether the Modal should appear, you can set some sort of identifiable value that tells it what item to load (and otherwise leave it undefined).
Bare-bones example:
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
export default function App() {
const [modalInfo, setModalInfo] = React.useState(undefined);
const renderItem = ({ item }) => (
<TouchableOpacity onPress={() => setModalInfo(item.title)}><Text>{item.title}</Text></TouchableOpacity>
);
return (
<View style={styles.container}>
<Modal visible={modalInfo !== undefined}>
<View style={[{borderWidth: 1},styles.centeredView]}>
<Text>{modalInfo}</Text>
<TouchableOpacity onPress={() => setModalInfo(undefined)}><Text>Close</Text></TouchableOpacity>
</View>
</Modal>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
);
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

React-Native-Swiper images Overflow ONLY ON ANDROID

I have a problem with react-native-swiper on Android ONLY. The same code works for iOS!
Below is an image of what is happening:
The area is blue is supposed to be a square and all images should be within it. Something like this (I only render 1 image here):
This is what my code looks like:
renderSwiper = () => {
const images = this.props.data.item[1].images;
let swiperImages = images.map((image, index) => {
let priority = FastImage.priority.normal;
if (index === 0)
priority = FastImage.priority.high;
return (
<TouchableWithoutFeedback key={index} onPress={this.routeToListingDetails} >
<FastImage
style={styles.imageStyle}
source={{uri: image, priority: priority}}
/>
</TouchableWithoutFeedback>
)
})
return (
<View style={{ aspectRatio: 1, width: '100%'}}>
<Swiper
loop={false}
paginationStyle={styles.swiperPaginationStyle}
>
{swiperImages}
</Swiper>
</View>
);
}
render(){
return (
<View style={styles.container} >
<View style={{ borderColor: 'blue', borderWidth: 2 }}>
{this.renderSwiper()}
</View>
</View>
)
}
const styles = StyleSheet.create({
container:{
width:'50%',
alignItems:'center',
marginBottom:'4%',
padding:'2%',
},
imageStyle:{
resizeMode: "cover",
width: "100%",
aspectRatio:1
}
})

Align all icon to the right of page regardless of start point React Native

I want to be able to align all reply icons to the far right, where the red line is, regardless of where they start.
Edit: added more information to show how recursion is used in the component. Why I try to use some answers that work without recursion, I receive an undesired effect.
This is the code I have in place so far:
class Comment extends Component {
render() {
return(
<View>
<Header
rounded
style={{
backgroundColor: '#ffffff',
position: 'relative',
}}
>
<View style={{flexDirection: 'row', flexWrap: 'wrap', right: '43%', top: '50%'}}>
<Icon name='chevron-left' size={10} color='#006FFF' style={{top: '6%'}}/>
<NativeText
onPress={() => this.props.history.push('/')}
style ={{color: '#006FFF', fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
Back
</NativeText>
</View>
</Header>
<View
style={{paddingLeft: '2%', paddingTop: '2%'}}
>
<CommentList
options={this.props.location.state.comments}
currentUser={this.props.location.state.currentUser}
history={this.props.history}
reportId={this.props.location.state.reportId}
optionsForBackButton={this.props.location.state.comments}
/>
</View>
</View>
)
}
}
export default withRouter(Comment)
const CommentList = ({options, currentUser, history, reportId, optionsForBackButton}) => {
return (
<View>
{options.map(option => (
<View
style={{flexDirection: 'row'}}
>
<NativeText
style={{fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
{option.content}
</NativeText>
<View
style={{flex: 1, alignItems: 'flex-end' }}
>
<Icon
name='reply'
size={12}
// onPress={() => {
// setModalVisible(true)
// changeParentId(option._id)
// }}
onPress={() => history.push({pathname: '/create-comment', state: {content: option.content, currentUser: currentUser, reportId: reportId, parentCommentId: option._id, optionsForBackButton: optionsForBackButton}})}
/>
</View>
{
<View
style={{left: '10%'}}
>
<CommentList
options={option.reply}
optionsForBackButton={optionsForBackButton}
history={history}
currentUser={currentUser}
reportId={reportId}
/>
</View>
}
</View>
))}
</View>
)
}
Set your icon containing view's flex value to 1. This should cause it to fill all remaining space.
See the following snack: https://snack.expo.io/#jrdndncn/playful-churros
class Comment extends React.Component {
render() {
return (
<View
style={{
marginVertical: 2,
flexDirection: 'row',
marginLeft: (this.props.indent || 0) * 20,
}}>
<Text>{this.props.text}</Text>
<View style={{ flex: 1, alignItems: 'flex-end' }}>
<View style={{ width: 20, height: 20, backgroundColor: 'red' }} />
</View>
</View>
);
}
}
<Comment text="hello" indent={0} />
<Comment text="hello" indent={1} />
<Comment text="hello" indent={2} />
Basically marginLeft:'auto' will do the trick. just add style to icon as :
<Icon
name='reply'
size={12}
style={{marginLeft:'auto'}}
// onPress={() => {
// setModalVisible(true)
// changeParentId(option._id)
// }}
onPress={() => history.push({pathname: '/create-comment', state: {content: option.content, currentUser: currentUser, reportId: reportId, parentCommentId: option._id, optionsForBackButton: optionsForBackButton}})}
/>
i added marginLeft:'auto' in style it will automatically shown at the right end of the screen.

implement tabs in the center of the screen

I am new to react native. i have implemented stacknavigator inside drawernavigator. Using this library
"react-navigation": "^1.0.0-beta.11",
Now i want to implement tabs within the screen at the center. Following image is part of my screen
i dont have any idea how can i do this with any library or manually putting views.
Any help is appreciated.
Thanks
Well, I've solved that scenario using react-native-swiper
Basically you have to wrap all views you want to have inside a Swiper, render and style the header as you want.
Here there is a working example I've made:
render() {
return (
<View style={styles.body}>
<Swiper
height={500}
showsPagination={true}
loop={false}
renderPagination={this._renderPagination}
ref={component => this._swiper = component}>
<View style={styles.page}>
<FlatList data={..} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
</Swiper>
</View>
);
}
_renderPagination(index, total, context) {
return (
<View style={styles.pagination}>
{this._renderPaginationHeaders(index, total, context)}
</View>
)
}
_renderPaginationHeaders(index, total, context) {
let ret = [];
for (let i = 0; i < total; i++) {
ret.push(
<TouchableOpacity key={i} style={{ flex: 1, flexDirection: 'column' }} onPress={() => this._onPageChange(i)}>
<Text style={[styles.title, { flex: 1, textAlign: 'center', textAlignVertical: 'center' }]}>
{this._getSectionText(i)}
</Text>
<View style={{ height: 5, backgroundColor: index === i ? 'magenta' : 'transparent' }}></View>
</TouchableOpacity>
);
}
return ret;
}
_onPageChange(targetIndex) {
const currentIndex = this._swiper.state.index;
const offset = targetIndex - currentIndex;
this._swiper.scrollBy(offset);
}
const styles = StyleSheet.create({
body: {
flex: 1,
alignItems: 'center',
alignSelf: 'center',
backgroundColor: '#f1f1f1',
},
pagination: {
flexDirection: 'row',
width: Dimensions.get('window').width,
height: Header.currentHeight * 0.7,
backgroundColor: '#2E2E2E',
paddingLeft: 2,
paddingRight: 2,
alignItems: 'center',
position: 'absolute',
top: 0,
},
page: {
flex: 1,
marginTop: (Header.currentHeight * 0.7) + 3
},
title: {
color: 'white'
},
});