-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[View] Keep view's aspect ratio based on new prop #1538
Conversation
@paramaggarwal - this is a really interesting idea! cc @vjeux An initial bit of feedback:
|
I think we want this in core since it achieves parity between static and network images and it's a fundamental that applies to all images. To be clear, @paramaggarwal's proposal maintains the current invariant of needing to specify the image size up front (before we've downloaded it from the network). The sole difference is that it's the intrinsic image size, not the displayed size (in the style prop) that needs to be specified. This provides a very consistent API for users that I could explain to people:
@paramaggarwal: might want to rename original width/height to intrinsic width/height to match w3c docs. |
Thanks @brentvatne and @ide. I have renamed originalHeight/originalWidth to intrinsicHeight/intrinsicWidth. I have also updated the calculated dimensions to be For the benefit of others, here is the flow of how the final dimensions of a network image are calculated in order of priority:
In all of these scenarios, if it is not able to calculate the height from the given info, it will attempt to use the aspect ratio computed from the dimensions passed to Travis test is failing because of this failure on
Also, should I extend this change to static images also? So that even static images would have the same behaviour in terms of calculating their height themselves given the intrinsic dimentions in |
var style = flattenStyle([{width, height}, styles.base, this.props.style]); | ||
if (isNetwork) { | ||
// NetworkImageView uses a measure method instead to set original width and height | ||
style = flattenStyle([styles.base, this.props.style]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're throwing away the work done in flattenStyle above - it can be quite expensive, so only do one or the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good one, I fixed this.
This is cool, but we have some changes planned with the source width/height that may need to coordinate here (although I think this is a better solution to the problems we've been seeing than we were planning). Assigning to @frantic who has been working on that image stuff. |
Also, can you rebase? It might also give a passing test run. |
4f7a87b
to
3858082
Compare
@sahrens Squashed commits into one, rebased to fix merge conflicts, removed redundant |
@frantic please share your thoughts. Also, I noticed while using this, that setting a Currently I do this:
So this works well. It works like an opt-in switch. Passing in Pinging @vjeux for thoughts regarding the use of css-layout |
In general, it's really important that the order of property changes not matter, just the final state - can you fix that? |
Btw image themselves may not be the only one that require an aspect ratio. If you want to do a responsive square grid, you need to maintain 1:1 aspect ratio on a View. Out of the scope of this pull request but would be nice to unify the concept of aspect ratio constraint |
Isn't this the default behaviour on the web already? When an Now in React Native, we do not load images and calculate dimensions, we expect the dimensions to be passed before-hand as part of This PR, helps us give the original In much this way, the
|
Hey @paramaggarwal, great work! I'm wondering if we could use the same logic for both static and network images? Or am I missing something? For more context about the image work we are doing internally. The idea is to deprecate Implementation wise we will be serving the images over network in development mode and will bundle them with the app when submitting to AppStore, so the same image will be rendered using NetworkImage and StaticImage depending on environment. That means they have to behave the same way to avoid surprises. As part of that, we made packager add width and height to image metadata, so the developer won't need to duplicate information that the system can figure out. The only problem with this approach is when the developer wants to use something like flex to size the image - width and height attributes we set get priority. One solution could be flattening style and checking if flex or alignSelf are set, and only if not - applying known width and height. |
Yes, this should absolutely happen.
Then, both the native implementations for static and remote images should take the provided intrinsic dimensions into account when computing layout.
The width and height properties of the image source should not get priority. They are intrinsic dimensions, not the rendered dimensions. Just like the web, they should be the defaults that the layout engine uses as a last resort. For example, if the programmer uses flex and we know the rendered width of the image should be 375px wide but don't know its rendered height, then the layout engine should calculate |
5122fcb
to
1b79184
Compare
Thanks @frantic, the behaviour of static and remote images is now exactly the same after my latest changes (which I have squashed into a single commit). I've published an example to https://github.com/paramaggarwal/flex-image-demo to demonstrate this. Thanks @ide, the behaviour you describe makes perfect sense, please try out the example I have published. Here is the index.ios.js file of the demo. |
I am trying the test cases described by @ide above.
This works, but without having to explicitly use
This works as expected.
This does not work as expected. When no I attempted to fix this by trying these modifications in my code:
But this still didn't work because css-layout uses only the height from the returned dimensions and not the width. It continues to use the width of the parent itself. The relevant snippet of code is here.
@vjeux please help with your thoughts here. Should this kind of layout be a method on css-layout instead? For example right now, we specify a |
Folks, please review! Also, if there is anything that should be done differently here, please share! |
Please review/share feedback! |
I've been using aspectRatio from @paramaggarwal's branch, and have not run into any problem. Absolutely essential! 👍 |
Folks, please review! |
It won't go into 0.10 because we've cut the RC and this isn't an urgent bugfix. I don't think it will go into 0.11 either because that release will focus on stability, but it could make it into 0.12-rc. For me to feel good about this commit I'd want aspectRatio to work in both dimensions. E.g. if you have an image with aspect ratio 4:3 and give it |
@ide Good point! That needs a change in css-layout - will leave this open till we get around to supporting it there. |
Till then, could someone please pull #1776? It was imported but never showed up on |
Anybody would like to help out on facebook/yoga#118? The idea is to make |
@paramaggarwal is there another issue I should watch? Would really like to see this happen... |
@hayeah Long story short, this PR depended on Basically the goal was to make Currently I am making do with having a fork of RN with #1776 merged in and then just having a small custom component called |
Very well done! But where is the doc? |
Any update on this? I could really use this in my project right now. :) |
@iostalk @wootwoot1234 The changes in this PR are able to support aspect ratio only in one dimension - for it to make it into core, it needs to support both vertical and horizontal dimensions. Unfortunately that needs serious rework on the |
Also needing this badly, what are the latest developments? Is there a way I can get this to work @paramaggarwal ? |
@alfrednerstu I should probably publish what I have as an OSS component. Haven't gotten around to doing it... |
Hey folks, here is the generic component I have been using to make an arbitrary container who's height is always in a particular ratio to its width. This width is equal to the width of the parent. Great for use with images where you want them to stick to a particular aspect ratio. Here is the code with the usage as a comment: https://gist.github.com/paramaggarwal/b9baa00fd7bee9a2948f Feel free to use the code anywhere and also make it into an OSS component. |
The changes needed in Should I make the change only for |
@paramaggarwal It would be nice as generic. I have a use case with react-native-video component where I'm wanting to use flex:1 for the width but maintain aspect ratio without having to provide a fixed height. I'm curious if this feature might help towards implementing flex-grow/shrink features? |
This feels a bit like css's: background-size:cover. Ideally, you would be able to specify how to position the image in the defined window. Normally, a centered approach would be best |
@paramaggarwal updated the pull request. |
docs: Remove advice to enable Fast Refresh for new apps
Continues from #858.
Current behaviour:
<Image source=require("image_name.jpg") />
, the packager adds thewidth
andheight
into thesource
prop. Hence there is no need of setting dimensions instyle
.width
andheight
is forcefully set on thestyle
prop, which means if one uses onlyalignSelf: 'stretch'
to layout the image, theheight
would not change in the same ratio as thewidth
inherited from the parent.This pull request fixes this. I believe the basic problem that this attempts to solve is very genuine. It includes a
measure
function on NetworkImageView to maintain aspect ratio of image when dimensions are known beforehand.Now just like automatic sizing and layout of text, the same would work for images that actually take the entire width of the device, and the height would be configured automatically based on the calculated aspect ratio of the image:
Open to suggestions on how to improve this pull request.