i have 12 card view on homescreen
im using Flat list to render the 12 cards
I have 2 columns set so 2 cards in the view
i would like to tweak it so after every 2 cards 1 card be full width then the next 2 cards next to each other and the third is full width and so on
here is my code
<FlatList
data={ this.state.GridListItems }
keyExtractor={(item) => item.id.toString()}
renderItem={ ({item, index}) =>
<TouchableOpacity style={{width: (index + 1) % 3 === 0 ? '108%' : '54%', height: '110%', justifyContent:'center', overflow: "hidden",
flex:1,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
backgroundColor: '#231F20',
borderRadius: 5,
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 6,
padding: 5,}}
onPress={() => this.props.navigation.navigate('ProfileScreen', { height: "6'2", category: item.key })}>
<ImageBackground
source={{ uri: item.img }}
style={{width: '108%', height: '110%', justifyContent:'center'}} >
<View style={{position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'center', alignItems: 'center'}}>
<Text style={styles.GridViewTextLayout} > {item.key} </Text>
</View>
</ImageBackground>
</TouchableOpacity>
}
numColumns={2}
initialNumToRender={6}
/>
i want it to render 2 cards (each card 50% of screen) and every third card (100% of the screen) for the 12 element
you can try this. so, on every third card, it should display the full width.
const styles = {
GridViewContainer: {
justifyContent:'center',
overflow: "hidden",
flex:1,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
backgroundColor: '#231F20',
borderRadius: 5,
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 6,
padding: 5,
}
}
<FlatList
data={this.state.GridListItems}
keyExtractor={(item) => item.id.toString()}
renderItem={({item, index}) =>
<TouchableOpacity
style={styles.GridViewContainer}
onPress={() => this.props.navigation.navigate('ProfileScreen', { height: "6'2", category: item.key })}
>
<ImageBackground
source={{ uri: item.img }}
style={{
width: (index + 1) % 3 === 0 ? '216%' : '108%',
height: '110%',
justifyContent: 'center',
}}
>
<View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text style={styles.GridViewTextLayout}> {item.key} </Text>
</View>
</ImageBackground>
</TouchableOpacity>
}
numColumns={2}
initialNumToRender={6}
/>
edited to reflect the styling for GridViewContainer
Related
native-card-flip" for creating flip cards and I need to have multiple flip cards so I have added that flip card in FlatList but the issue is that the list is not scrolling at all. I have tried it with ScrollView and .map() function but scrolling not working at all.
<FlatList
data={revision}
renderItem={({item, index}) => (
<CardFlip
style={{
width: width * 0.95,
height: height * 0.3,
marginBottom: height * 0.015,
marginTop: height * 0.015,
}}
duration={3000}
ref={card => (this['card' + index] = card)}>
<Card
style={{
width: width * 0.9,
borderRadius: 16,
backgroundColor: 'transparent',
height: height * 0.8,
}}>
<TouchableOpacity onPress={() => this['card' + index].flip()}>
<View
style={{
flexDirection: 'row',
backfaceVisibility: 'hidden',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: Colors.lightGrey,
borderRadius: 22,
width: width * 0.95,
height: height * 0.3,
}}>
<Text
style={{
color: Colors.heading,
textAlign: 'center',
marginBottom: 1,
fontSize: 20,
width: '92%',
}}>
Lorem Ipsum
</Text>
</View>
<View
style={{
position: 'absolute',
bottom: 10,
right: 10,
}}>
{/* <TouchableOpacity
onPress={() => {
this.card.flip();
setIsFlipped(!isFlipped);
}}
style={{justifyContent: 'flex-end'}}> */}
<Image
source={require('../assets/images/flip-front.png')}
/>
{/* </TouchableOpacity> */}
</View>
</TouchableOpacity>
</Card>
<Card
style={{
width: width * 0.95,
borderRadius: 16,
backgroundColor: 'transparent',
height: height * 0.8,
alignSelf: 'center',
}}>
<TouchableOpacity
style={{
width: width * 0.95,
height: height * 0.3,
}}
onPress={() => this['card' + index].flip()}>
{/* Flip Back */}
<View
style={{
flexDirection: 'column',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flex: 1,
paddingHorizontal: width * 0.05,
backgroundColor: Colors.white,
borderRadius: 22,
}}>
<Text
style={{
color: Colors.heading,
fontSize: 20,
marginBottom: '2%',
fontFamily: 'FiraSans-ExtraBold',
}}>
Lorem Ipsum
</Text>
<Text
style={{
color: Colors.heading,
fontSize: 16,
marginBottom: '2%',
textAlign: 'justify',
fontFamily: 'OpenSans-Regular',
}}>
{strings.dummyText}
</Text>
</View>
<View
style={{
position: 'absolute',
bottom: 10,
right: 10,
}}>
{/* <TouchableOpacity
onPress={() => {
this.card.flip();
setIsFlipped(!isFlipped);
}}
style={{justifyContent: 'flex-end'}}> */}
<Image source={require('../assets/images/flip-back.png')} />
{/* </TouchableOpacity> */}
</View>
</TouchableOpacity>
</Card>
</CardFlip>
)}
numColumns={1}
keyExtractor={(item, index) => index.toString()}
style={{marginTop: height * 0.01}}
showsVerticalScrollIndicator={false}
maxToRenderPerBatch={1}
/>
Please help me to figure out how can I achieve scrolling.
here is my code: Basically I want to render the list in absolute view but it's not working in android,
when I tested this code on IOS it works fine
<View
style={[
styles.shadow,
{
position: 'absolute',
top: 47,
width: '95%',
borderBottomRightRadius: 15,
borderBottomLeftRadius: 15,
backgroundColor: '#fff',
zIndex: 1,
maxHeight: metrics.height * 0.35,
...dropdownStyle
},
]}>
<FlatList
contentContainerStyle={{ position: 'absolute', zIndex: 9000 }}
scrollEnabled={true}
keyExtractor={item => item.filter_id}
data={data}
renderItem={({ item, index }) => {
return <Tc key={index}
onPress={() => onPress(item)}
style={{
zIndex: 100,
borderTopWidth: index == 0 ? 0 : 0.5,
borderTopColor: colors.grey,
backgroundColor: 'transparent',
paddingHorizontal: 10,
paddingVertical: 15,}}>
<Text
style={{textTransform:'capitalize'}}
testID={'searchDropdownOption'}
accessibilityLabel={'searchDropdownOption'}>
{item.filter_name}
</Text>
</Tc>
</View>
this above code is the view I have render in my screen.
TL;DR
It is uncertain that when will the audio file be fetched and given to the trackplayer. So i need a way that will detect the change that the file has been fetched and duration value is now available. I tried playing around with Async/await but it still fails to deliver the duration value on time to the slider.
I am developing an RN app that can stream the audio files that are currently stored in my firebase storage. I am facing difficulty in updating the slider's maximumValue. Since the song takes a couple of seconds to get fetched from firebase, the (total) duration value of the song file given by the react-native-track-player is undefiend and consequently the play button's onPress function setState(duration) sets the new tracklength state as undefined. And this is set as the maximumValue for the slider, which in turn gives the error as shown in the screenshot.
What can i do such that, when the TrackPlayer.getState() (a method from the ProgressComponent) changes its value to 'playing' or 'Ready', the application automatically rerenders with the correct duration value without giving the error.
I have used React-native-slider and React-native-Track-player
/* eslint-disable react-native/no-inline-styles */
import React from 'react';
import { Text, View, Image, SafeAreaView, TouchableOpacity, Platform, StatusBar, Dimensions, Modal, Button } from 'react-native';
import Slider from 'react-native-slider';
import Moment from 'moment';
import DeviceInfo from 'react-native-device-info';
import { FontAwesome5, Feather, Entypo } from '#expo/vector-icons';
import { Surface, Card, Badge } from 'react-native-paper';
import TrackPlayer, { ProgressComponent, getPosition } from 'react-native-track-player';
import storage from '#react-native-firebase/storage';
export default class MusicPlayer extends ProgressComponent {
componentWillMount() {
TrackPlayer.setupPlayer().then(async () => {
await TrackPlayer.add({
// url: 'https://sampleswap.org/mp3/artist/5101/Peppy--The-Firing-Squad_YMXB-160.mp3',
url: (await storage().ref('Songs/01 - Luck Aazma - www.downloadming.com.mp3').getDownloadURL()).toString(),
});
}
).then(console.log('aaaaaaaaaaaaaaaaaaaaaaa ' + this.getS().then(res => console.log(res))));
// .then(async () => {
// var dur = (await TrackPlayer.getDuration()).toString();
// this.setState({ trackLength: dur });
// });
// const temp = await TrackPlayer.getState();
// if (temp === TrackPlayer.STATE_READY) { console.log('its ready here') }
}
// componentDidMount() {
// this.interval = setInterval(
// () => {
// this.forceUpdate;
// }, 3500
// );
// }
// componentWillUnmount() {
// clearInterval(this.interval);
// }
constructor(props) {
super(props);
this.state = {
trackLength: 300,
timeElapsed: '0:00',
timeRemaining: '5:00',
optionsVisible: false,
curr_time: 0,
isPlaying: false,
t_state: this.getS(),
};
}
seekTime = seconds => {
this.setState({ timeElapsed: Moment.utc(seconds * 1000).format('m:ss') });
TrackPlayer.seekTo(seconds);
this.setState({ timeRemaining: Moment.utc((this.state.trackLength - seconds) * 1000).format('m:ss') });
};
setCurr = seconds => {
return Moment.utc(seconds * 1000).format('m:ss');
};
getS = async () => {
return await TrackPlayer.getState();
}
render() {
return (
<SafeAreaView style={{ backgroundColor: '#2d545e', flex: 1, paddingTop: (DeviceInfo.hasNotch && Platform.OS === 'android') ? StatusBar.currentHeight : 0 }}>
<View style={{ margin: 3, flex: 1 }}>
<TouchableOpacity
style={{ alignSelf: 'flex-end', marginRight: 10 }}
onPress={this.toggleOverlay} >
<Entypo name="dots-three-vertical" size={24} color="white" />
</TouchableOpacity>
{/* playlist name and album name */}
<View style={{ alignItems: 'center', marginTop: -25 }}>
<Text style={{ color: '#FFFFFF', fontSize: 10 }}>PLAYLIST</Text>
<Text style={{ color: '#FFFFFF', fontFamily: 'sans-serif', fontWeight: '500' }}>Album_name_here</Text>
</View>
{/* song image/ thumbnail zone */}
<Surface raised style={{ marginTop: 30, height: 200, width: 200, alignSelf: 'center', elevation: 50, borderRadius: 30 }}>
<Image source={{ uri: 'https://a10.gaanacdn.com/images/albums/61/161/crop_480x480_161.jpg' } || require('../../assets/images/temp.jpeg')} style={{ height: 200, width: 200, borderRadius: 30, alignSelf: 'center' }} />
</Surface>
{/* song name and artist name */}
<View style={{ marginTop: 25, flexDirection: 'column', alignItems: 'center' }}>
<Text style={{ color: '#FFFFFF', fontFamily: 'sans-serif', fontWeight: 'bold', fontSize: 20 }}>Song_Name_here</Text>
<Text style={{ color: '#FFFFFF', fontFamily: 'sans-serif', fontWeight: '500', marginTop: 3 }}>artist_name_here</Text>
</View>
{/* slider component only */}
<View style={{ flexDirection: 'column', alignItems: 'center', marginTop: 8 }}>
<Slider
minimumValue={0}
value={this.state.position}
animationType="timing"
maximumValue={this.state.trackLength}
trackStyle={{ width: Dimensions.get('screen').width - 50, height: 4 }}
thumbStyle={{ height: 20, width: 20, backgroundColor: '#fff' }}
thumbTouchSize={{ width: 100, height: 40 }}
minimumTrackTintColor="#000000"
onSlidingComplete={seconds => { console.log(seconds); this.seekTime(seconds); }}
/>
<View style={{ width: Dimensions.get('screen').width - 35, backgroundColor: '#', flexDirection: 'row', justifyContent: 'space-between' }}>
<Text style={{ flex: 1 }}>{this.setCurr(this.state.position)}</Text>
<Text style={{ alignSelf: 'flex-end' }}>{this.setCurr(this.state.trackLength)}</Text>
</View>
</View>
{/* repeat, back, play, forward and shuffle button */}
<View style={{ width: '95%', height: 70, backgroundColor: '#', alignSelf: 'center', margin: 15, flexDirection: 'row' }}>
<TouchableOpacity style={{ flex: 1, height: 30, width: 10, alignSelf: 'center', justifyContent: 'space-between', alignItems: 'center' }}>
<Feather
name="repeat"
size={30}
color="#000000"
style={{ alignItems: 'center' }}
/>
</TouchableOpacity>
<TouchableOpacity style={{ flex: 1, height: 30, width: 10, alignSelf: 'center', justifyContent: 'space-between' }} onPress={() => TrackPlayer.skipToPrevious()}>
<FontAwesome5 name="backward" size={32} color="#242320" style={{ alignSelf: 'center' }} />
</TouchableOpacity>
{
// this.state.t_state === TrackPlayer.STATE_READY &&
!this.state.isPlaying && <TouchableOpacity
style={{ flex: 1, height: 50, alignSelf: 'center', justifyContent: 'space-between', alignItems: 'center' }}
onPress={async () => {
TrackPlayer.play().then(this.setState({ isPlaying: true })).then(async () => {
var dur = (await TrackPlayer.getDuration()).toString();
this.setState({ trackLength: dur });
});
}}
>
<FontAwesome5
name="play"
size={38}
color="#000000"
style={{ marginTop: 5 }}
/>
</TouchableOpacity>}
{this.state.isPlaying && <TouchableOpacity style={{ flex: 1, height: 50, alignSelf: 'center', justifyContent: 'space-between', alignItems: 'center' }} onPress={() => TrackPlayer.pause().then(this.setState({ isPlaying: false }))}>
<FontAwesome5
name="pause"
size={38}
color="#000000"
style={{ marginTop: 5 }}
/>
</TouchableOpacity>}
<TouchableOpacity style={{ flex: 1, height: 30, width: 10, alignSelf: 'center', justifyContent: 'space-between' }} onPress={() => TrackPlayer.skipToNext()}>
<FontAwesome5 name="forward" size={32} color="#242320" style={{ alignSelf: 'center' }} />
</TouchableOpacity>
<TouchableOpacity style={{ flex: 1, height: 30, width: 10, alignSelf: 'center', justifyContent: 'space-between', alignItems: 'center' }}>
<Entypo
name="shuffle"
size={30}
color="#000000"
style={{ alignItems: 'center' }}
/>
</TouchableOpacity>
</View>
{/* up next section */}
<Surface raised style={{ width: '95%', backgroundColor: 'black', alignSelf: 'center', height: 70, borderRadius: 10, marginTop: 5 }}>
<Card.Title
style={{ backgroundColor: 'white', flex: 1, borderRadius: 10 }}
title={'Song Name here'}
titleStyle={{ margin: 25, padding: 0 }}
left={() =>
<Image
style={{ width: 50, height: 50, borderRadius: 10, alignSelf: 'flex-start', alignItems: 'flex-start' }}
source={require('../../assets/images/temp.jpeg')}
/>
}
leftStyle={{ alignItems: 'flex-start', margin: -10, padding: 0 }}
right={() => <Badge children={'Next'} size={30} style={{ width: 70, backgroundColor: 'black', borderRadius: 5, marginRight: 10 }} />}
/>
</Surface>
</View>
</SafeAreaView>
);
}
}
Sorry for the messy code but the comments would help a bit in navigating to the main parts like Slider and Play Button
Error:
My Error from the slider
For those who might require an answer to this, I solved the problem using React Hooks. React Native Track Player has a v2 update, in which the converting the above class component to functional component did the trick. It gives a rather accurate results then before. Refer to the docs here.
I am creating a barcode scanner using expo-barcode-scanner
I have created the below screen the whole screen is transparent
I am trying to create the below screen only the QR code square is transparent
<BarCodeScanner
style={styles.mainContainer}>
<TouchableOpacity
onPress={() => {
navigation.navigate('Home')
}}
style={styles.backButton}
>
<Entypo
style={{ color: Colors.SAWhite }}
name="chevron-thin-left"
size={25}
/>
</TouchableOpacity>
<View style={styles.qrContainer}></View>
<View style={styles.messageBox}>
<FontAwesomeIcon
name="qrcode"
size={50}
style={isValid ? styles.initialColor : styles.errorColor}
/>
{isValid ? (
<Text style={[fonts.SemiBoldTitle, styles.initialColor]}>
{Languages.Scanner.initialMessage}
</Text>
) : (
<Text style={[fonts.SemiBoldTitle, styles.errorColor]}>
{Languages.Scanner.errorMessage}
</Text>
)}
</View>
</BarCodeScanner>
styles
const styles = StyleSheet.create({
mainContainer: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden',
},
backButton: {
alignSelf: 'flex-start',
marginLeft: '5%',
},
qrContainer: {
width: 220,
height: 220,
borderColor: Colors.SAWhite, //white
borderWidth: 1,
margin: '10%',
},
messageBox: {
width: '85%',
height: '30%',
backgroundColor: Colors.SAWhite,
borderColor: Colors.SABlack,
borderWidth: 1,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'space-evenly',
},
initialColor: {
color: Colors.SASecondary,//grey
textAlign: 'center',
marginLeft: '10%',
marginRight: '10%',
},
errorColor: {
color: Colors.SARed,
textAlign: 'center',
marginLeft: '10%',
marginRight: '10%',
},
})
I have tried to wrap it around a view but it also makes the center box as coloured
i have tried expo's barcode code but it is also not good implementation
You can build up the overlay around the transparent part using multiple absolute positioned views, leaving the center empty.
const scanOverlay = {
position: 'absolute',
backgroundColor: 'rgba(255,0,0,0.5)',
};
<View>
<Camera />
<View style={StyleSheet.absoluteFill}>
<View style={[scanOverlay, {top: 0, left: 0, width: '25%', bottom: 0}]} />
<View style={[scanOverlay, {top: 0, left: '25%', right: '25%', height: '25%'}]} />
<View style={[scanOverlay, {bottom: 0, left: '25%', right: '25%', height: '25%'}]} />
<View style={[scanOverlay, {top: 0, right: 0, width: '25%', bottom: 0}]} />
</View>
</View>;
clicking this position absolute button is not working when I touch it.
code
render() {
return (
<Container>
<View style={{ borderColor: '#fff',height:'30%'}}>
<ImageBackground
source={{uri: 'https://i.ibb.co/TwdZhVM/image-5.png'}}
style={styles.singleCategoryViewBackgroundImage} >
</ImageBackground>
<View style={styles.overlay}>
<Thumbnail large
style={styles.profileImage}
source={{uri:"https://firebasestorage.googleapis.com/v0/b/weddi-4c344.appspot.com/o/Laser%20%26%20Beauty%20Centers%2FDivine%20beauty%20clinics%2FLogo.jpg?alt=media"}} />
<View style={styles.titleContent}>
<Text style={styles.titleText}> Divine Beauty Center</Text>
<Text note>Cairo - Naser City</Text>
<View style={{flexDirection: 'row'}}>
<Button rounded style={styles.actionButton}
onPress={() =>
ActionSheet.show(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
title: "Testing ActionSheet"
},
buttonIndex => {
this.setState({ clicked: BUTTONS[buttonIndex] });
}
)}
>
<Icon ios="ios-pin" android="md-pin" color="#1a1917"/>
</Button>
<Button rounded style={styles.actionButton}>
<Icon ios="ios-call" android="md-call" color="#1a1917"/>
</Button>
</View>
</View>
</View>
</View>
<Content style={{paddingHorizontal: '6%', marginTop: '20%', height: '20%'}}>
</Content>
</Container>
styles
overlay: {
alignItems: 'center',
height: '65%',
backgroundColor: colors.offWhite,
position: 'absolute',
top: '68%',
left: 0,
right: 0,
bottom: 0,
zIndex: 1,
marginHorizontal: '6%',
borderRadius: 10/2,
opacity: 0.95,
},
singleCategoryViewBackgroundImage: {
width: '100%',
height: '100%',
justifyContent:'center',
alignContent:'center',
},
profileImage: {
position: 'absolute',
top: '-38%',
left: '36%',
right: 0,
bottom: 0,
zIndex: 2,
alignSelf: 'center',
overflow: 'hidden',
borderWidth: 2,
borderColor: '#b42334',
width: 100,
height: 100,
borderRadius: Platform.OS === 'ios' ? 0 : 150/2,
},
titleContent: {
zIndex: 40,
marginVertical: '15%',
alignItems: 'center',
},
titleText: {
fontFamily: 'Roboto',
fontWeight: 'bold',
},
actionButton: {
width:50,
zIndex: 50,
margin: '2%',
backgroundColor: colors.red,
}
I tried replacing the native-base button with react native button still doesn't work but when I make the button outside this position absolute mess it works great but I like how it looks inside this view so any ideas how can I get it to work that way?
From https://www.w3schools.com/cssref/pr_pos_z-index.asp: "Note: z-index only works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky)." Since actionButton doesn't specify a position attribute, it's position is the default position value (static) and z-index does not apply. So your absolutely positioned Views are on top of your button.