React Native Maintaining aspect ratio image ios - image

I have a 1242 X 450 image, which I’d like to display on a 1x 2x and 3x devices. The current code, which I have, works fine for 3x devices but I see that the edge of the image gets cropped on a 2x device and possible on a 1x device too.
In code I am setting width to 414 and height to 150 (because 1242 X 450 /3x)
Is there any way I can fix it?
The image is inside a list view
<View style={styles.row}>
<Image
style={styles.featureImage}
source={{
uri: this.props.image_src
}}/>
</View>
const styles = StyleSheet.create({
row: {
alignItems: 'center',
backgroundColor: 'lightgrey',
flexDirection: 'row',
margin: 6,
},
featureImage: {
height: 150,
width: 414
}
});

You don't need to deal with image's size. You just give width and height property properly.
import Platform and get width and height of device.https://facebook.github.io/react-native/docs/dimensions.html
var {scrHeight, scrwidth} = Dimensions.get('window');
define an image container style
imageContainer = {
width:scrwidth/5,
height:scrHeight/5,
}
define image style and use resizeMode for image
resizeMode enum('cover', 'contain', 'stretch', 'repeat', 'center')
imageStyle={
flex:1,
}
<View style={styles.imageContainer }>
<Image style={styles.imageStyle} resizeMode={'contain'}>
</Image>
</View>
No matter how big the image is it will cover screenWidth/5 X screenHeight/5.
If your image has high resolution and device is not the image will be compressed in the contrary case it will be stretched. Both case especially second one if there is a big difference between image resolution and area which is left for image you will have bad image vision in your app. To avoid this situation you can add different sizes of the same image.
add
└── img
├── apple#1x.png 100x100 (resolutions are random)
└── apple#2x.png 150x150
apple#3x.png 175x175
https://facebook.github.io/react-native/docs/images.html
If you do so proper image will be chosen by react automatically. Images are chosen according to dpi of device. If your device has nice resolution you get bigger image if not so smaller image. This situation mostly works except devices having big sizes and low resolutions( some android tablets). In this case according to dpi image will be probably smallest image so there will be a bad quality.

Related

Decrease the size of the cropper crop box

[1]I am using react-cropper to crop and upload an image. But I have been trying to reduce the size of "cropper-crop-box", that's the size of the selector in image without points, so I wanna decrease the size of that circle[react-cropper] and fix it's size, but initialAspectRatio is stopping me from setting it's size. Or if anyone knows how to decrease the size of that cropping circle with initialAspectRatio, that's also okay. Please help me with this.
<ImageCropper
style={{
height: 400,
width: "100%",
}}
ref={cropperRef}
cropmove={onCropMove}
zoomTo={0.5}
initialAspectRatio={1}
aspectRatio={NaN}
src={URL.createObjectURL(file[0])}
viewMode={2}
minCropBoxHeight={50}
minCropBoxWidth={5}
background={false}
responsive={true}
autoCropArea={2}
checkOrientation={false}
onInitialized={(instance) => {
setCropper1(instance);
}}
guides={false}
cropBoxMovable={true}
movable={true}
/>

Hitting maxsize issues for canvas element on iOS for small canvas

I'm working on a whiteboard app (JS/HTML) which uses a canvas element wrapped with fabric.js.
I'm aware of certain size limitations with the canvas element, however I'm scratching my head as to why to why my canvas fails to render at all on iOS even at relatively small sizes of 2300 x 1200 pixels.
I've prepared a small demo below. On my iPhone XS this only renders the grey div, no canvas. If I drop the canvas size down to say 1500 x 1200 it works.
This is at odds what this canvas size capability checker tells me which states my phone being capable of a 4096 x 4096 pixel canvas.
// create a wrapper around native canvas element (with id="c")
var canvas = new fabric.Canvas('c');
// create a rectangle object
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 60,
height: 60
});
// "add" rectangle onto canvas
canvas.add(rect);
canvas.setBackgroundColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.3.1/fabric.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.0.2/tailwind.min.css" rel="stylesheet"/>
<div class="m-10 bg-gray-400 w-3/4 h-64 overflow-x-auto overflow-y-auto">
<canvas id="c" width='2300' height="1200"></canvas>
</div>
Any pointers much appreciated.
I've now worked out that fabric creates a canvas at twice the configured size on retina screens which means that a configured width of 2300px for the fabric object actually results in a canvas of 4600px width which in turn exceeds the device capabilities.
What I still don't know is how to work around this so that I can create a larger canvas on some iOS devices such as my phone which declares a capability of 4096x 4096px.
The added complexity is that we share the canvas in realtime between different devices so one screen may be retina and one may be standard resolution.

How to display both portrait & landscape images into a square on the grid without disturbing the aspect ratio?

I am using a GridView to create a gallery of images that I display from a certain folder on my machine. The images are of different width*height ratios. Few are portrait images where the height of the image is like 3 times more than width. Some image are landscape like where the width is approx 3 times of height. And some images are squared.
The issue with my gallery is I have a square for each Image component of my GridView as you can see below. This makes the portrait & landscape images get incorrectly stretched as each block in the Grid is a square. Thus causing the aspect ratio of the image to get skewed up.
The Question:
How can I ensure that I display both portrait & landscape images into my square without skewing the aspect ratio? I am looking at putting some black/grey background on parts of the square which go blank on a portrait or landscape image? But there might be other tricks.
The code:
import QtQuick 2.5
import Qt.labs.folderlistmodel 2.1
import QtQuick.Controls 1.1
import QtQml.Models 2.1
GridView {
cellHeight: height/2
cellWidth: width/2
clip: true
FolderListModel {
id: dir_model
folder: "/path/to/images/folder"
nameFilters: ["*.png"]
}
Component {
id: file_delegate
Image {
width: (parent.width)/2
height: (parent.width)/2
source: fileURL
}
}
model: dir_model
delegate: file_delegate
}
Just set Image fillMode property to Image.PreserveAspectFit
As the doc says:
the image is scaled uniformly to fit without cropping

Wrapping text around an image with React-Native

I try to create a View with an Image and a Text component that wraps around the Image component.
My styling:
textContainer: {
flexDirection: 'row',
},
text: {
flex: 10,
},
image: {
flex:1,
height: 180,
width: 150,
margin: 10,
borderColor: '#ccc',
borderWidth: 1,
}
My component:
<ScrollView style={styles.contentContainer} >
{this.props.content.title_1 ? <Text style={styles.title}>{this.props.content.title_1}</Text> : null}
<View style={styles.textContainer}>
{this.props.content.text_1 ? <Text style={styles.text}>{this.props.content.text_1}</Text> : null}
{this.props.content.image_1 ? <Image width={null} height={null} style={styles.image} source={this.props.content.image_1} /> : null}
</View>
</ScrollView>
This is what the result: (not wrapping at all haha)
In the image beneath here, I quickly hacked the little image into the text. But I can't get the text to be wrapped around..
I hope anyone can help me in the right direction!
This is really hard but there is one weird way to do this.. Try the following. It worked for me but place I am doing this is too deep in the other views.:
<Text>
<View style={{width:400, height:100, flex:1, flexDirection:'row'}}>
<Image source={require('')}/>
<Text>Your Content Here</Text>
</View>
</Text>
Good luck. Please put a comment letting us know if it worked.
On android you cannot place a View inside Text, but you can place an Image, here is an example:
<Text>
<Image source="" />
<Text> Insert your text here </Text>
</Text>
Although this is an old post, I'll add this because I have recently had this problem and found a totally different approach that works for me. I don't have the code to hand (I can get it if anyone wants it), but the principle was this:
Requirement: to have a picture in the top left corner of the screen that takes up about half the screen width, with text starting to the right of it and then continuing beneath it for the whole width of the screen.
In XML, create a RelativeLayout containing an ImageView (IV) on the left and a TextView (TVA), set to wrap content, on the right. Then create another TextView (TVB) to sit below the Relative Layout. TVA is for the text beside the image and TVB for the text beneath it.
Put your image in IV. Then measure the height of IV in pixels (dpi). Call this height IVh
Put some of your text in TVA. As long as there is enough text to wrap over several lines, it doesn't really matter how much. Then measure the height of TVA in pixels. Call this height TVh
Compare IVh with TVh. If IVh=TVh then you have just the right amount of text to sit alongside your image. If TVh = IVh x 2 then you have twice as much text as you should have. And so on.
Adjust the number of words accordingly and put the right number into TVA, replacing what was there, then put the rest of the text in TVB.
You will need to play with margins and padding to allow an adequate margin around the image. Also, in steps 3 and 4 after you have put your image into ImageView or your text into TextView, you will need a delay before measuring the heights, to allow the display to be created - otherwise the measurement will be done too soon, before there is anything on the screen, and will return a height of zero. I found 200 milliseconds quite adequate and it's too fast for the user to notice a delay.

how to handle different screen sizes in react native?

I am developing an application on react-native. I have made a UI which works fine on iPhone 6 but not working fine on iPhone 5 or lower versions.
How should I fix this ?
You need to think about proportion when building your UI.
1, Use percentage(%) for width and aspectRatio for height, or vice versa.
container: {
width: "100%",
aspectRatio: 10 / 3, //height will be "30%" of your width
}
2, Use flex for the jobs percentage can't do. For example, if you have arbitrary size of items in a list and you want them to share equal sizes. Assign each of them with flex: 1
3, Use rem from EStyleSheet instead of pixels. rem is a scale fator. For example, if your rem is 2 and your “11rem” will become “11*2” = “22”. If we make rem proportion to the screen sizes, your UI will scale with any screen sizes.
//we define rem equals to the entireScreenWidth / 380
const entireScreenWidth = Dimensions.get('window').width;
EStyleSheet.build({$rem: entireScreenWidth / 380});
//how to use rem
container: {
width: "100%",
aspectRatio: 10 / 3, //height will be "30%"
padding: "8rem", //it'll scale depend on the screen sizes.
}
4, Use scrollView for contents that could potentially scale out of the boxes. For example, a TextView
5, Every time you think about using pixels, consider use rem in method 3.
For a detailed explanation, you can read the article here. 7 Tips to Develop React Native UIs For All Screen Sizes
Have you designed the app using fixed widths and heights? You should definitely use the capabilities of flexbox and try to avoid settings fixed sizes as much as possible. The flex property can be used to define how much space a <View /> should use releative to others, and the other properties on that page can be used to lay out elements in a flexible way that should give the desired results on a range of different screen sizes.
Sometimes, you may also need a <ScrollView />.
When you do need fixed sizes, you could use Dimensions.get('window').
You need to calculate sizes dynamically, relying on screen size.
import { Dimensions, StyleSheet } from 'react-native'
[...]
const { width, height } = Dimensions.get('window')
[...]
const styles = StyleSheet.create({
container: {
flex: 1.
flexDirection: 'column',
},
myView: {
width: width * 0.8, // 80% of screen's width
height: height * 0.2 // 20% of screen's height
}
})
If you are using TabbarIOS, remember that Dimensions.get('window') gives you the whole screen's height, this means that you'll have to take in account that the tabbar has fixed-height of 56.
So for example, when using TabbarIOS:
const WIDTH = Dimensions.get('window').width,
HEIGHT = Dimensions.get('window').height - 56
Then use WIDTH and HEIGHT as above.

Resources