Image cannot go full-width in react-native - android

I want to make a screen with a full-width Android screen image, but however, for some reason I cannot do it. I have done every single solution available in SO but it still persists.
Here is my code:
<View style={styles.loginContainer}>
<Image
style={styles.background}
source={require('./image.png')}
//source={{uri: 'http://previews.123rf.com/images/background.jpg'}}
opacity={0.8}
>
<Login navigator={navigator} />
</Image>
</View>
and my Stylesheet:
var styles = StyleSheet.create({
loginContainer: {
alignSelf: 'stretch',
flex: 1,
alignItems: 'stretch'
},
background: {
alignSelf: 'stretch',
flex: 1,
alignItems: 'stretch'
},
});
For some reason it worked just fine when I used network images, but when I used static images, it will only cover 2/3 width but full height. I have also tried source={{uri: 'image.png', isStatic: true}}, but it gives me null error. Any solution is much appreciated. Thanks.

Yes, there is an open issue on Github.
First of all, I would suggest using the resizeMode property, for instance:
<Image
style={styles.background}
source={require('./image.png')}
opacity={0.8}
resizeMode="contain"
>
Then, for network images, this would work:
var styles = StyleSheet.create({
loginContainer: {
flex: 1,
},
background: {
flex: 1,
},
});
For 'required' images, it does not work, as you pointed out, so you can either specify the width yourself:
var width = require('Dimensions').get('window').width;
var styles = StyleSheet.create({
loginContainer: {
flex: 1,
},
background: {
flex: 1,
width: width,
},
});
Or even set it to null:
var styles = StyleSheet.create({
loginContainer: {
flex: 1,
},
background: {
flex: 1,
width: null,
},
});

You can use react-native-scalable-image. The following example will give you a full screen width image:
import React from 'react';
import { Dimensions } from 'react-native';
import Image from 'react-native-scalable-image';
const image = <Image width={Dimensions.get('window').width} source={{uri: '<image uri>'}} />;

try this android:scaleType="fitXY"
<ImageView
android:id="#+id/image_view_full"
android:layout_width="fill_parent"
android:scaleType="fitXY"
android:layout_height="fill_parent" />

Related

React Native image takes up all vertical space available

I am new to react-native (started 2 days ago) but I picked it up quickly because I already knew regular react. I'm trying to write a real world app and I can't figure out how to place an image correctly, I want my Image tag to take up all horizontal space on the screen, but I also want it to stay at the very top of the screen and keep its aspect ratio (which I can't hardcode because I will also display other pictures of licence plates, including european ones that are not 2/1 like in north america), all while not having the actual image take up all available vertical space.
Here is a GIMP edit of what my code renders and what I actually want:
https://ibb.co/XJgrhkC
Here is my render function:
export default class App extends Component {
...
render() {
return (
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'center' }}>
<Image
source={require(`./resources/images/north_america/original/alaska.jpg`)}
style={{ flex: 1, width: screenWidth }}
resizeMode="contain" />
<Button title="Random state" onPress={this.getRandomState} />
</View>
);
}
}
I am familiar with css's layout options but react-native seems to be different and I can't wrap my head around all the combinations of widths, flex and resizeModes.
typically, upon applying flex to the <View /> tag enclosing the <Image /> and the <Button />, the children of the parent component will have the same flex prop applied. so, you can remove the flex prop under <Image />.
having dealt with <Image /> in react-native for some time, i must say that specifying values for both height and width is important for an <Image /> to be displayed properly.
you can try it out on my Expo example here.
render() {
return (
<View style={{
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center'
}}>
<Image
source={require(`./resources/images/north_america/original/alaska.jpg`)}
style={{
width: screenWidth,
height: 200,
}}
resizeMode="contain"
/>
<Button
title="Random state"
onPress={this.getRandomState}
/>
</View>
);
}
also, since you are new to react-native, may i suggest you change <Button /> to <TouchableOpacity />? it provides a visual aid when user presses it on a mobile device.
When you use flex, you can see the image automatically occupying a lot of space when you add {borderWidth: 2, borderColor: 'red'}. Instead, you have to specify the height manually. If you want it to be scaled properly, you can try this:
import React from "react";
import { View, Image, Button, Dimensions } from "react-native";
class App extends React.Component {
state = {
imgWidth: 0,
imgHeight: 0
};
componentDidMount() {
Image.getSize("https://i.ibb.co/HgsfWpH/sc128.jpg", (width, height) => {
// Calculate image width and height
const screenWidth = Dimensions.get("window").width;
const scaleFactor = width / screenWidth;
const imageHeight = height / scaleFactor;
this.setState({ imgWidth: screenWidth, imgHeight: imageHeight });
});
}
render() {
return (
<View
style={{ flex: 1, justifyContent: "flex-start", alignItems: "center" }}
>
<Image
style={{
flex: 1,
width: Dimensions.get("window").width,
borderColor: "red",
borderWidth: 2
}}
source={{
uri: "https://i.ibb.co/HgsfWpH/sc128.jpg"
}}
resizeMode="contain"
/>
<Button title="Random state" onPress={this.getRandomState} />
</View>
);
}
}
export default App;

<Image> url not showing for android React Native

I am using <Image> and <ImageBackground> with source:{{ uri: url }} inside my React Native project.
But the problem is an image is not showing inside Android simulator (But IOS simulator is fine)
This is my component
import React from 'react'
import {
Text, StyleSheet, ImageBackground, Image,
} from 'react-native'
import { Header } from 'react-navigation'
import { dimens } from '../../../services/variables'
const CustomHeader = ({ bgSrc }) => (
<ImageBackground
source={
bgSrc
? { uri: bgSrc }
: require('../../../assets/images/placeholder_image_bg_wide.png')
}
style={styles.header}
>
<Text style={styles.description}>First element</Text>
<Image source={{ uri: 'https://i.vimeocdn.com/portrait/58832_300x300.jpg' }} style={{ width: 200, height: 45, backgroundColor: 'red' }} />
<Text style={styles.description}>Second element</Text>
<Image source={{ uri: 'http://i.vimeocdn.com/portrait/58832_300x300.jpg' }} style={{ width: 200, height: 45 }} />
<Text style={styles.title}>Last element 1</Text>
</ImageBackground>
)
export default CustomHeader
const styles = StyleSheet.create({
header: {
minHeight: Header.HEIGHT,
height: dimens.header.height,
marginTop: dimens.header.marginTop,
paddingLeft: dimens.header.paddingLeft,
paddingBottom: dimens.header.paddingBottom,
backgroundColor: 'blue',
flexDirection: 'column-reverse',
},
title: {
...dimens.header.title,
},
description: {
...dimens.header.description,
},
})
I also already added permissions inside AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
This is the image of my both simulators
You will see that on IOS simulator <Image> is showing correctly but not on Android none images were show (Both http and https)
So how can i fix these and make Android simulator works, Thanks!
I have said this before in another question
https://stackoverflow.com/a/71263771/8826164
but there is an issue with Image component is that if first time initialize the component with source={{uri : 'some link'}} it may not work (at least not for me when I fetch image from HTTPS URL from Firebase storage). The trick is you have to trigger a change to source props like first you need to keep
source to source={undefined} and then change to source={{uri : 'some link'}}. And it seems like you have hard-coded URL for uri, so you might fall into the same issue as I did
Before :
<Image source={{ url: http://stitch2stitch.azurewebsites.net/assets/img/FileFormats/${result}.png}} style={{ height: 40, width: 40, }} />
After :
<Image source={{uri: http://stitch2stitch.azurewebsites.net/assets/img/FileFormats/${result}.png}} style={{ height: 40, width: 40, }} />
just change from url to uri works for me

Right is Left on React Native

Trying to display a List item within renderRow.
I already implemented RTL in my project as defined on react native documentation, and I am getting a positive for console.log(I18nManager.isRTL ? 'yes' : 'no').
I am trying to present a designed table cell, so it's an image, on top of which I am trying to layout my items.
So the logo is defined in styles like this:
var styles = StyleSheet.create({
logo:{
position: 'absolute',
top:11,
right:11,
width: 26,
height: 26
}
frame: {
flex: 1,
flexDirection: 'row',
margin: 5,
},
txtFirstName:{
position:'absolute',
top:7,
right:40,
marginRight:36,
color:'white',
fontSize:PixelRatio.get()*4/PixelRatio.getFontScale(),
fontWeight:'bold',
textAlign:'right',
textShadowColor: 'black',
textShadowOffset: {width:2,height:2},
writingDirection : 'rtl'
},
txtSecondName:{
position:'absolute',
top:17,
right:40,
marginRight:36,
color:'white',
fontSize:PixelRatio.get()*3/PixelRatio.getFontScale(),
fontWeight:'bold',
textAlign:'right',
textShadowColor: 'black',
textShadowOffset: {width:2,height:2},
writingDirection : 'rtl'
},
txtMainText:{
position:'absolute',
marginRight:36,
color:'white',
fontWeight:'bold',
textAlign:'right',
textShadowColor: 'black',
textShadowOffset: {width:2,height:2},
writingDirection : 'rtl',
fontSize:PixelRatio.getPixelSizeForLayoutSize(3),
},
});
renderRow(rowData, sectionID, rowID) {
return(
<TouchableOpacity onPress={()=>this.showBusiness(rowData)}>
<View style={{flex:1}}>
<Image style={styles.logo} resizeMode = 'cover' source=}require('../images/logo.png’){/>
<Image source={require('../images/mainFrame.png’){ style={styles.frame}/>
<Text style={[styles.txtMainText,styles.txtFirstName]}>
טקסט
</Text>
<Text style={[styles.txtMainText,styles.txtSecondName]}>
מיושר לימין
</Text>
</View>
</TouchableOpacity>
);
}
The result is disappointing.
Here's how it should look like:
and here's how it is right now:
What bothers me most is that it used to look okay, and I am not sure what blew it this way.
Also, the "Loading" text shows on the right of the window when the app starts.
As according to the documentation: "we map the left/right styles from the JS side to start/end, all left in code for RTL layout becomes "right" on screen, and right in code becomes "left" on screen."... Have you considered using left instead of right for your positioning? Alternatively, consider using flex-start or flex-end for the desired result.

How to design screens in react native compatible for all devices

I am trying to design this design react-native. This is what I have coded for this but this is not what I want. This works on one screen only, if I change screen size then things are not working.
This looks like absolute layout. What changes should I make to make it in such a way so that it will work on all screen sizes.
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from "react";
import {
AppRegistry,
Image,
View,
Text,
Button,
StyleSheet
} from "react-native";
class SplashScreen extends Component {
render() {
console.disableYellowBox = true;
return (
<View style={styles.container}>
<Image
source={require("./img/talk_people.png")}
style={{ width: 300, height: 300 }}
/>
<Text style={{ fontSize: 22, textAlign: "center", marginTop: 30 }}>
Never forget to stay in touch with the people that matter to you.
</Text>
<View style={{ marginTop: 60, width: 240 }}>
<Button title="CONTINUE" color="#FE434C" />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#FFFFFF",
margin: 50,
alignItems: "center",
flex: 1,
flexDirection: "column"
}
});
AppRegistry.registerComponent("Scheduled", () => SplashScreen);
Expected State:
Current State:
Nexus 4 - 768x1280
Nexus 6P - 1440x2560
The quick answer is to use flex within your outer container, such that you have, say:
<View style={{flex: 1}}>
<View style={{flex: 2}}>
<.../>//Image
</View>
<View style={{flex: 1}}>
<.../>//Text
</View>
<View style={{flex: 1}}>
<.../>//Button
</View>
</View>
which will divide the container into quarters and give the top half of the screen to the image and the other two quarters to the text and button; you can use padding and margins with these as you like, and use any ratio you want.
What further needs to be considered, though, is screen pixel density, which can really wreak havoc with display sizes. I've found it handy to have an outside
import React from 'react';
import { PixelRatio } from 'react-native';
let pixelRatio = PixelRatio.get();
export const normalize = (size) => {
switch (true){
case (pixelRatio < 1.4):
return size * 0.8;
break;
case (pixelRatio < 2.4):
return size * 1.15;
break;
case (pixelRatio < 3.4):
return size * 1.35;
break;
default:
return size * 1.5;
}
}
export const normalizeFont = (size) => {
if (pixelRatio < 1.4){
return Math.sqrt((height*height)+(width*width))*(size/175);
}
return Math.sqrt((height*height)+(width*width))*(size/100);
}
module which I use as
import { normalize, normalizeFont } from '../config/pixelRatio';
const {width, height} = require('Dimensions').get('window');
...and for an image, say:
<Image source={ require('../images/my_image.png') } style={ { width: normalize(height*.2), height: normalize(height*.2) } } />
and a font:
button_text: {
fontSize: normalizeFont(configs.LETTER_SIZE * .7),
color: '#ffffff'
},
Hope this helps!
Edit: The module above has worked for me for devices I've deployed to, but it should be expanded to allow for pixelRatio values of from 1 to 4 with some decimal (e.g. 1.5) values in there, too. There's a good chart at this link that I'm working from to try to finish this out, but so far what has worked best is as I've posted above.
Another great way of creating dynamic layout is by using the Dimensions, Personally I hate flex (couldn't understand it at times) Using Dimensions You could get the screen width and height. After which you could divide the result and assign them to top level components
import React, { Component } from "react";
import {
View,
StyleSheet,
Dimensions
} from "react-native";
const styles = StyleSheet.create({
container: {
backgroundColor: "#FFFFFF",
height: Dimensions.get('window').height,
width: Dimensions.get('window').width,
//height:Dimensions.get('window').height*0.5// 50% of the screen
margin: 50,
alignItems: "center",
flex: 1,
flexDirection: "column"
}
});
Also adding to this, came across this library that supports media queries, if you are comfy with css styles just give it a try

Charts not getting displayed with react-native-chart-android

I am trying to use the react-native-chart-android library for including charts in my android app.
I installed the module successfully and went through the provided examples as is. Everything went fine without errors but the graphs are not getting rendered somehow.
I am trying out the LineChart (which is itself in a separate View) within a ScrollView along with ToolbarAndroid and one more View on the same level on RN 0.20. Do let me know if I am missing something.
Thanks in advance.. :)
PS: Code snippet for reference (removed the trivial parts of the code for better visualisation)
import {
LineChart
} from 'react-native-chart-android';
class Dashboard extends Component {
render() {
return (
<ScrollView style={styles.scrollView}>
<ToolbarAndroid ... />
<View style={styles.container}>
...
</View>
<View style={styles.chartContainer}>
<LineChart style={{flex:1}} data={this.getLineData()}/>
<LineChart
style={{flex:1}}
data={this.getRandomData()}
visibleXRange={[0,30]}
maxVisibleValueCount={50}
xAxis={{drawGridLines:false,gridLineWidth:1,position:"BOTTOM"}}
yAxisRight={{enable:false}}
yAxis={{startAtZero:false,drawGridLines:false,position:"INSIDE_CHART"}}
drawGridBackground={false}
backgroundColor={"BLACK"}
description={"description"}
legend={{enable:true,position:'ABOVE_CHART_LEFT',direction:"LEFT_TO_RIGHT"}} />
</View>
<Text style={styles.description}>{this.state.message}</Text>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'stretch',
backgroundColor: '#F5FCFF'
},
scrollView: {
flex: 1
},
chartContainer: {
flex: 1
}
});
I had same problem, my conclusion was that ScrollView renders only children with height and width. Although you set flex:1 around charts, I think they are larger then ScrollView and that's why they are not visible inside of ScrollView. I've set height and width to my charts, and gave them min and max Y -> if you set flag startAtZero:false you should set axisMinValue and axisMaxValue. For example: yAxis={{startAtZero:false,drawGridLines:false,position:"INSIDE_CHART", axisMinValue: 20, axisMaxValue: 500}}
And for charts try to set custom width and height:
chartContainer: {
flex: 1,
height: 500, //any value you want
width: 500 //any value you want
}
I've set half of device height and full width with Dimensions:
import { Dimensions } from 'react-native';
var {height, width} = Dimensions.get('window');
chartContainer: {
flex: 1,
height: height/2,
width: width
}
And after that my charts are visible inside of ScrollView!
Hope it helps! :)

Categories

Resources