is there a way to arrange this layout so that the image is on the left, and the button is on the right?
Right now, it just displays with the image at the top left, and the button that spans the whole width of the screen right below.
Thanks!
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>
Hello, Chat App!
</Text>
<Image
style={{width: 50, height: 50}}
source={getFunction(1)}
/>
<Button
style={{width: 50, height: 50}}
onPress={ () => navigate('Chat', { user: 'Abe', avatar: getFunction(1) })}
title = "Chat with Abe"
/>
<Image
style={{width: 50, height: 50}}
source={getFunction(2)}
/>
<Button
onPress={ () => navigate('Chat', { user: 'Jack', avatar: getFunction(2) })}
title = "Chat with Jack"
/>
<Image
style={{width: 50, height: 50}}
source={getFunction(3)}
/>
<Button
onPress={ () => navigate('Chat', { user: 'Kate', avatar: getFunction(3) })}
title = "Chat with Kate"
/>
);
}
}
You can try this:
The below code snippet is for alignment of one image and one button.
<View style={{ flex: 1, flex-direction: 'row', justifyContent: 'space-between' }}>
<View style={{ margin: 15 }} >
<Image style={{width: 50, height: 50}} source={getFunction(1)} />
</View>
<View style={{ margin: 15 }} >
<Button style={{width: 50, height: 50} onPress={ () => navigate('Chat', {
user: 'Abe', avatar: getFunction(1) })} title = "Chat with Abe" />
</View>
</View>
Cheers :)
Related
Like in tinder, i have a screen with 3 Image Pickers. When I pick an image from the gallery, I want it to persist inside the TouchableOpacity container. However, the image overlaps the container.
I have been been trying various things mentioned here but the image still overlaps like in the image below:
What is the problem?
/* eslint-disable react-native/no-inline-styles */
import React, { useState } from 'react'
import {
Text,
View,
Image,
Button,
TouchableOpacity,
StyleSheet,
Dimensions,
} from 'react-native'
import ImagePicker from 'react-native-image-crop-picker'
import { FontAwesomeIcon } from '#fortawesome/react-native-fontawesome'
import { faPlusCircle } from '#fortawesome/free-solid-svg-icons'
import Colors from '../../../constants/Colors'
const { width: WIDTH } = Dimensions.get('window')
const ProfileEdit = () => {
const [photo, setPhoto] = useState(null)
const handleChoosePhoto = () => {
ImagePicker.openPicker({
width: 300,
height: 400,
cropping: true,
}).then((image) => {
setPhoto({
uri: image.path,
width: image.width,
height: image.height,
mime: image.mime,
})
console.log(image)
})
}
return (
<View style={styles.main}>
<View style={styles.button_row}>
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
{photo ? (
<Image source={photo} style={styles.photo} />
) : (
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
)}
</TouchableOpacity>
</View>
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
</TouchableOpacity>
</View>
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
</TouchableOpacity>
</View>
</View>
</View>
)
}
const styles = StyleSheet.create({
main: {
flex: 1,
},
icon: {},
button: {
height: `${100}%`,
backgroundColor: Colors.defaultWhite,
padding: 2,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 3,
},
buttonWrapper: {
width: WIDTH / 3,
padding: 10,
},
button_row: {
flex: 0.3,
flexWrap: 'wrap',
flexDirection: 'row',
},
photo: {
width: WIDTH / 2,
height: WIDTH / 2,
// borderRadius: 3,
resizeMode: 'contain',
},
})
export default ProfileEdit
correct answer as described here
"However because images will try to set the width and height based on the actual size of the image, you need to override these style properties"
<Image
style={{
flex: 1,
alignSelf: 'stretch',
width: undefined,
height: undefined
}}
source={require('../../assets/images/onboarding-how-it-works.png')}
/>
Instead of calculating image width try this:
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
{photo ? (
<View style={styles.photoContainer}>
<Image source={photo} style={styles.photo} />
</View>
) : (
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
)}
</TouchableOpacity>
const styles = StyleSheet.create({
photoContainer: {
// flex: 1
},
photo: {
height: WIDTH / 2,
width: '100%',
resizeMode: 'contain'
}
});
I prefer ImageBackground instead. Below is the code to achieve you the desired View:
<ImageBackground
imageStyle={styles.image}
style={styles.imageContainer}
source={{uri: this.state.imageUri}}>
<TouchableOpacity onPress={this._pickImage} style={{
height: WIDTH/2,
width: WIDTH/2,
justifyContent: "center",
alignItems: "center"}}>
<Entypo name="camera" color={Colors.GREY} size={35}/>
</TouchableOpacity>
</ImageBackground>
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.
I want to play a audio on card, when click on the play icon, it plays, i update player state to playing and want to change play icon to pause icon. But cant re-render the card. I have read https://github.com/alexbrillant/react-native-deck-swiper/issues/153 but no solution, how to solve this ?
setPlay2(index, sound, stopper = false) {
....
this.setState({
playing: 'playing',
});
.....
}
const {
playing
} = this.state;
....
<Swiper
ref={(swiper) => {
this.swiper = swiper;
}}
cards={data}
cardIndex={cardIndex}
renderCard={card => (
<View style={{ flex: 1 }}>
<TouchableOpacity onPress={() => this.setPlay2()}>
{
playing === 'playing' ? (
<Image source={require('#images/BasicAppMenu/pause.png')} style={{ height: 32, width: 32 }} />
) : (
<Image source= {require('#images/BasicAppMenu/play.png')} style={{ height: 32, width: 32
}} />
)
}
</TouchableOpacity>
</View>
)}
/>
Just to check playing within the <TouchableOpacity> element - is this this.state.playing ? You've not included all the code.
If not, this may work?
<TouchableOpacity onPress={() => this.setPlay2()}>
{
this.state.playing === 'playing' ? (
<Image source={require('#images/BasicAppMenu/pause.png')} style={{ height: 32, width:
32 }} />
) : (
<Image source= {require('#images/BasicAppMenu/play.png')} style={{ height: 32,
width: 32
}} />
)
}
</TouchableOpacity>
Right now I have a react-native-elements-header with a react-native-snap-carousel wrapped in a simple container as below:
render() {
return (
<View style={styles.container}>
<Header
outerContainerStyles={styles.header}
leftComponent={
<Text style={styles.heading}>{this.state.title}</Text>
}
rightComponent={
<Icon
name='account-circle'
color={COLOR_LIGHT_SECONDARY}
onPress={() => this.props.navigation.navigate('Settings')} />
}
/>
{this.cardCarousel}
</View>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 26,
height: 26,
},
container: {
flex: 1,
backgroundColor: "white",
},
containerCentered: {
justifyContent: 'center',
alignItems: 'center',
},
header: {
//flex: 2,
height: '15%',
},
heading: {
fontSize: TITLE,
fontWeight: 'bold',
color: THEME_COLOR,
},
card: {
backgroundColor: THEME_COLOR
}
});
and this.cardCarousel returns a carousel with pagination:
get cardCarousel() {
const { activeSlide, entries } = this.state;
var phoneWidth = Dimensions.get('window').width;
return (
<View style={styles.containerCentered}>
<Carousel
ref={(c) => { this._carousel = c; }}
data={entries}
renderItem={this._renderItem}
sliderWidth={phoneWidth}
itemWidth={phoneWidth*0.85}
/>
<Pagination
dotsLength={this.state.entries.length}
activeDotIndex={activeSlide}
containerStyle={{}}
dotStyle={{
width: 8,
height: 8,
borderRadius: 4,
marginHorizontal: 0,
backgroundColor: THEME_COLOR
}}
inactiveDotStyle={{
// Define styles for inactive dots here
}}
inactiveDotOpacity={1}
inactiveDotScale={0.6}
/>
</View>
);
}
However cardCarousel is overlayed on top of the header. I have tried many props for container and containerCentered but the cardCarousel is always overlaying header and is aligned from the top. What am I doing wrong here? I have also attached a screenshot below:
react-native-elements-header is absolute positioned element, because of header being absolutely positioned carousel is rendered on top of header.
check this once
https://github.com/react-native-training/react-native-elements/blob/8d4f85890bc37da64fa9712b166a92dd13b2e0a3/src/header/Header.js
<Header
outerContainerStyles={styles.header}
leftComponent={
<Text style={styles.heading}>{this.state.title}</Text>
}
rightComponent={
<Icon
name='account-circle'
color={COLOR_LIGHT_SECONDARY}
onPress={() => this.props.navigation.navigate('Settings')} />
}
/>
so give position relative for header outerContainerStyles.
<Header
outerContainerStyles={{position: "relative", height: "15%"}}
leftComponent={
<Text style={styles.heading}>{this.state.title}</Text>
}
rightComponent={
<Icon
name='account-circle'
color={COLOR_LIGHT_SECONDARY}
onPress={() => this.props.navigation.navigate('Settings')} />
}
/>
I make a chat app and I want to put the TextInput at the bottom of the page, but I can't manage to do it . If I try with position: 'absolute' + bottom: 0 the display is empty. I think I have a problem with a flex in my style , I'm not sure.
Here's my code for MessageScreen:
render() {
return (
<Wallpaper>
<KeyboardAvoidingView behavior='padding'>
<View>
<TextInput
style={styles.input}
onChangeText={text => this.setState({ message: text })}
// value={this.state.email}
placeholderTextColor='white'
underlineColorAndroid='transparent'
/>
<Button onPress={this.send} title='SEND' />
</View>
</KeyboardAvoidingView>
</Wallpaper>
);
}
}
const styles = StyleSheet.create({
text: {
color: 'white',
fontWeight: 'bold',
backgroundColor: 'transparent',
paddingLeft: 25
},
input: {
backgroundColor: 'rgba(255, 255, 255, 0.4)',
width: DEVICE_WIDTH ,
height: 40,
color: '#ffffff'
},
image: {
width: 40,
height: 40
}
});
Here's the Wallpaper:
render() {
return (
<Image style={styles.picture} source={require('src/components/images/wallpaper.png')}>
{this.props.children}
</Image>
);
}
}
const styles = StyleSheet.create({
picture: {
flex: 1,
width: undefined,
height: undefined,
resizeMode: 'cover'
}
});
try this.
<View style={styles.container}>
<KeyboardAvoidingView
style={{position: 'absolute', left: 0, right: 0, bottom: 0}}
behavior="position"
>
<TextInput
style={styles.input}
onChangeText={text => this.setState({ message: text })}
// value={this.state.email}
placeholderTextColor='white'
underlineColorAndroid='transparent'
/>
<Button onPress={this.send} title='SEND' />
</KeyboardAvoidingView>
</View>
working example can found here