React-Native-Swiper images Overflow ONLY ON ANDROID - react-native

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
}
})

Related

hotizonatal scroll in ScrollView on click of button react native

I am using horizontal ScrollView to show few items on screen, this scroll view has pagination enabled and I am able to show pagination on the screen as well.
Below is my code:
const SwipeScreen = () => {
const { width, height } = Dimensions.get('window');
const [sliderState, setSliderState] = useState({ currentPage: 0 });
const setSliderPage = (event) => {
const { currentPage } = sliderState;
const { x } = event.nativeEvent.contentOffset;
const indexOfNextScreen = Math.floor(x / width);
if (indexOfNextScreen !== currentPage) {
setSliderState({
...sliderState,
currentPage: indexOfNextScreen,
});
}
};
const { currentPage: pageIndex } = sliderState;
const scrollViewRef = useRef(null);
const toNextPage = () => {
sliderState.currentPage += 1;
scrollViewRef.current?.scrollTo({
x: window.width * sliderState.currentPage,
animated: true,
});
};
return (
<>
<ScrollView
style={{ flex: 1 }}
ref={scrollViewRef}
horizontal={true}
scrollEventThrottle={16}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
onScroll={(event) => {
setSliderPage(event);
}}
>
<View style={{ width, height }}>
<Text>Item 1</Text>
<Button title='Next' color='#f194ff' onPress={toNextPage} />
</View>
<View style={{ width, height }}>
<Text>Item 2</Text>
<Button title='Next' color='#f194ff' onPress={toNextPage} />
</View>
<View style={{ width, height }}>
<Text>Item 3</Text>
<Button title='Next' color='#f194ff' onPress={toNextPage} />
</View>
<View style={{ width, height }}>
<Text>Item 4</Text>
<Button title='Next' color='#f194ff' onPress={toNextPage} />
</View>
<View style={{ width, height }}>
<Text>Item 5</Text>
</View>
</ScrollView>
<View style={styles.paginationWrapper}>
{Array.from(Array(5).keys()).map((key, index) => (
<View
style={[
styles.paginationDots,
{ opacity: pageIndex === index ? 1 : 0.2 },
]}
key={index}
/>
))}
</View>
</>
);
};
const styles = StyleSheet.create({
textColor: {
color: 'red',
},
paginationWrapper: {
position: 'absolute',
bottom: 200,
left: 0,
right: 0,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
},
paginationDots: {
height: 10,
width: 10,
borderRadius: 10 / 2,
backgroundColor: '#0898A0',
marginLeft: 10,
},
});
export default WelcomeSwipeImgScreen;
I also wanted a next button, on whose click next item is shown on screen. For this I have written toNextPage function, but its not working. I am not able to figure out where I am going wrong with this

Card drop-down on react native

Is it possible to achieve a component drop on react native?
Something like this. Sorry for the paint skills. Thank you in advance .
You can create a custom component like below, You can change the render label to support the view you want.
This sample needs the data to be like the below object but you can create your own object.
const dataArray = [{value: 'Car', id: 1,},{value: 'Van',id: 2},{ value: 'Bus',id: 3}];
//Usage
<CustomDropDown data={dataArray} />
const CustomDropDown = (props) => {
const [open, setOpen] = React.useState(false);
const [selected, setSelected] = React.useState(-1);
const renderLabel = (item) => {
return (
<View
style={{
width: 200,
height: 60,
borderWidth: 1,
borderRadius: 10,
padding: 5,
marginVertical: 3,
}}>
<Text style={{ fontSize: 20 }}>{item.value}</Text>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text>{item.value}</Text>
<Text style={{ fontSize: 15 }}>{item.value}</Text>
</View>
</View>
);
};
const renderItem = (item) => {
return (
<TouchableOpacity
onPress={() => {
setSelected(item.id);
setOpen(!open);
//Call back to external state
}}>
{renderLabel(item)}
</TouchableOpacity>
);
};
return (
<View>
<TouchableOpacity style={{}} onPress={() => setOpen(!open)}>
{selected === -1 && <Text>Place holder text</Text>}
{selected !== -1 &&
renderLabel(props.data.find((x) => x.id === selected))}
</TouchableOpacity>
{open && (
<View
style={{
position: 'absolute',
top: 70,
}}>
{props.data.map((item) => renderItem(item))}
</View>
)}
</View>
);
};

Last odd flatlist item stretches along screen

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.

How to show Scrollview images horizontally having 2 columns

Hii i want to display images horizontally having 2 columns for this i am using scrollview but i dont know how to do that , i am using following code
code to fetch api
componentDidMount(){
return fetch('https://www.json-generator.com/api/json/get/ccLAsEcOSq?indent=1')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.book_array,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
code for render
render() {
if (this.state.isLoading === true) {
return <ActivityIndicator color={'red'} />;
}
return (
<View style={styles.container}>
<ScrollView horizontal={true}>
{this.state.dataSource.map(item => this.renderItem(item))}
</ScrollView>
</View>
);
}
}
code for renderItem
renderItem(item) {
return (
<View style={{ margin: 5 }}>
<View style={{
backgroundColor: 'red',
width: 150,
height: 150,
marginBottom: 1,
}}>
<Image style={{ width: 150,height: 150}}
source={{uri: item.image}}/>
</View>
<View style={{
backgroundColor: 'red',
width: 150,
height: 150,
marginBottom: 1,
}}>
<Image style={{ width: 150,height: 150}}
source={{uri: item.image}}/>
</View>
</View>
);}
Instead of ScrollView try FlatList which provides numColumns props which lets you allow to use columns as per your choice.
Instead of this,
<ScrollView horizontal={true}>
{this.state.dataSource.map(item => this.renderItem(item))}
</ScrollView>
Use this,
<FlatList
data={this.state.dataSource}
numColumns={2}
renderItem={this.renderItem}
/>
For more details of FlatList see Official Docs Here
Try flex-direction property:
renderItem(item) {
return (
<View style={{ margin: 5, flex: 1, flexDirection: "row", justifyContent: "space-around" }} >
<View style={{ backgroundColor: "red", width: 150, height: 150, marginBottom: 1 }} >
<Image style={{ width: 150, height: 150 }} source={{ uri: item.image }} />
</View>
<View style={{ backgroundColor: "red", width: 150, height: 150, marginBottom: 1 }} >
<Image style={{ width: 150, height: 150 }} source={{ uri: item.image }} />
</View>
</View>
);}
modify your ScrollView component Like this:
<ScrollView horizontal={true} contentContainerStyle={{height:300, flexWrap:'wrap'}}>
{this.state.dataSource.map(item => this.renderItem(item))}
</ScrollView>
Use flat list inside scroll view like this
<FlatList
horizontal={true}
data={this.state.dataSource}
renderItem={({ item }) => (this.renderItem({item}))}
/>
rearrange dataSource like this
array1 = [obj1,obj2,obj3,obj4,obj5,obj6,obj7,
array2=[[obj1,obj2],[obj3,obj4],[obj5,obj6],[obj7,obj8]]
and then render item with 2 rows.
didn't find any other way
To create view as you required need to implement your custom logic. In render function call a intermediate function to get columns in two row:
render() {
if (this.state.isLoading === true) {
return <ActivityIndicator color={'red'} />;
}
return (
<View style={styles.container}>
<ScrollView horizontal={true}>
{this.renderHorizantol(this.state.dataSource)}
</ScrollView>
</View>
);
In renderHorizantol function need to set up logic for even or odd rows, i am implementing this on index of dataSource Array:
renderHorizantol = (dataSource) =>{
let view = []
for(let i=0 ; i < data.length ; i = i+2)
{
let subView = this.renderItem(dataSource[i],dataSource[i+1])
view.push(subView)
}
return view
}
In renderItem function pass two element to draw upper and lower row contents:
renderItem(item1,item2) {
let image1 = item1["imageUrl"]
let image2 = item2 ? item2["imageUrl"] : null
return (
<View style={{ margin: 5 }}>
<View style={{
backgroundColor: 'red',
width: 150,
height: 150,
marginBottom: 1,
}}>
<Image style={{ width: 150,height: 150}}
source={{uri: image1}}/>
</View>
<View style={{
backgroundColor: 'red',
width: 150,
height: 150,
marginBottom: 1,
}}>
<Image style={{ width: 150,height: 150}}
source={{uri: image2}}/>
</View>
</View>
);}

React-Native: how to fill fullsize screen without explicit Width and Height?

I want to create a fullsize-screen with the child-view (a video player) that is rendered over the full size of the screen. I only get it work when i pass explicitly width and height to the component.
But i know that there is a property called "flex". In many tutorials they do something like "flex: 1", but for me it nowhere does what it is supposed to.
(For the sake of completeness, the video-player is not part of the question. I can also replace the <video> tag with <Image> or each other kind of view and get the same results)
render() {
const uri = this.props.uri
return (
<KeyboardAwareScrollView keyboardShouldPersistTaps="always" >
<TouchableWithoutFeedback onPress={RouterActions.pop}>
<Video source={{uri: uri}}
ref={(ref) => {
this.player = ref
}}
style={s.fullsize}
/>
</TouchableWithoutFeedback>
<TouchableOpacity onPress={RouterActions.pop} style={s.closeBtn}>
<Icon name="times-circle-o" size={20} color="white" />
</TouchableOpacity>
</KeyboardAwareScrollView>
)
}
My styles:
This is only working when i pass the width and height:
const s = StyleSheet.create({
fullsize: {
backgroundColor: 'black',
//flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
closeBtn: {
position: 'absolute',
left: 20,
top: 25,
},
});
I only tried out this one, but then the screen will be empty because of the -Component has a width and height of 0 each.
const s = StyleSheet.create({
fullsize: {
backgroundColor: 'black',
flex: 1, // this is not working
left: 0,
right: 0,
top: 0,
bottom: 0
},
});
I believe doing flex: 1 will make it take up all the space provided by it's parent element. In your case, none of your parent elements have any styling so try this out:
render() {
const uri = this.props.uri
return (
<View style={{ flex: 1 }}>
<TouchableWithoutFeedback style={{ flex: 1 }} onPress={RouterActions.pop}>
<Video source={{uri: uri}}
ref={(ref) => {
this.player = ref
}}
style={{ flex: 1 }}
/>
</TouchableWithoutFeedback>
<TouchableOpacity onPress={RouterActions.pop} style={s.closeBtn}>
<Icon name="times-circle-o" size={20} color="white" />
</TouchableOpacity>
</View>
)
}