Skip to content

Commit

Permalink
feat: Adding support for objectFit a partial equivalent to the resize…
Browse files Browse the repository at this point in the history
…Mode style and prop of <Image>. (#34576)

Summary:
This PR aims to add support for objectFit a partial equivalent to the resizeMode style and prop of Image.

## Changelog

[General] [Added] - Add support for objectFit style of Image.

Pull Request resolved: #34576

Test Plan:
1. Open the RNTester app and navigate to the Image page
2. See the Object Fit section.

![Screenshot_1662112702](https://user-images.githubusercontent.com/8868908/188115315-5d5aa971-93ba-4437-a54b-c5ea69b00c08.png)

Reviewed By: rickhanlonii

Differential Revision: D39261176

Pulled By: jacdebug

fbshipit-source-id: 1eefd76b6c11ed5fc52b2c524ad78c91051077f6
  • Loading branch information
gedeagas authored and facebook-github-bot committed Sep 8, 2022
1 parent 4d04b1d commit b2452ab
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 4 deletions.
1 change: 1 addition & 0 deletions Libraries/Components/View/ReactNativeStyleAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
overlayColor: colorAttributes,
resizeMode: true,
tintColor: colorAttributes,
objectFit: true,
};

module.exports = ReactNativeStyleAttributes;
19 changes: 17 additions & 2 deletions Libraries/Image/Image.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import NativeImageLoaderAndroid from './NativeImageLoaderAndroid';

import TextInlineImageNativeComponent from './TextInlineImageNativeComponent';

import {convertObjectFitToResizeMode} from './ImageUtils';

import type {ImageProps as ImagePropsType} from './ImageProps';
import type {RootTag} from '../Types/RootTagTypes';
import {getImageSourcesFromImageProps} from './ImageSourceUtils';
Expand Down Expand Up @@ -187,6 +189,14 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
},
};

const objectFit =
style && style.objectFit
? convertObjectFitToResizeMode(style.objectFit)
: null;
// $FlowFixMe[prop-missing]
const resizeMode =
objectFit || props.resizeMode || (style && style.resizeMode) || 'cover';

return (
<ImageAnalyticsTagContext.Consumer>
{analyticTag => {
Expand All @@ -205,15 +215,20 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
return (
<TextInlineImageNativeComponent
style={style}
resizeMode={props.resizeMode}
resizeMode={resizeMode}
headers={nativeProps.headers}
src={src}
ref={forwardedRef}
/>
);
}

return <ImageViewNativeComponent {...nativePropsWithAnalytics} />;
return (
<ImageViewNativeComponent
{...nativePropsWithAnalytics}
resizeMode={resizeMode}
/>
);
}}
</TextAncestor.Consumer>
);
Expand Down
12 changes: 10 additions & 2 deletions Libraries/Image/Image.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import type {ImageProps as ImagePropsType} from './ImageProps';
import type {ImageStyleProp} from '../StyleSheet/StyleSheet';
import NativeImageLoaderIOS from './NativeImageLoaderIOS';

import {convertObjectFitToResizeMode} from './ImageUtils';

import ImageViewNativeComponent from './ImageViewNativeComponent';
import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes';
import {getImageSourcesFromImageProps} from './ImageSourceUtils';
Expand Down Expand Up @@ -127,8 +129,14 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
}
}

// $FlowFixMe[prop-missing]
const resizeMode = props.resizeMode || style.resizeMode || 'cover';
const objectFit =
// $FlowFixMe[prop-missing]
style && style.objectFit
? convertObjectFitToResizeMode(style.objectFit)
: null;
const resizeMode =
// $FlowFixMe[prop-missing]
objectFit || props.resizeMode || (style && style.resizeMode) || 'cover';
// $FlowFixMe[prop-missing]
const tintColor = props.tintColor || style.tintColor;

Expand Down
21 changes: 21 additions & 0 deletions Libraries/Image/ImageUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/

type ResizeMode = 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';

export function convertObjectFitToResizeMode(objectFit: string): ResizeMode {
const objectFitMap = {
contain: 'contain',
cover: 'cover',
fill: 'stretch',
'scale-down': 'contain',
};
return objectFitMap[objectFit];
}
2 changes: 2 additions & 0 deletions Libraries/StyleSheet/StyleSheetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ export type ____TextStyle_Internal = $ReadOnly<{
export type ____ImageStyle_InternalCore = $ReadOnly<{
...$Exact<____ViewStyle_Internal>,
resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat',
objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down',
tintColor?: ____ColorValue_Internal,
overlayColor?: string,
}>;
Expand All @@ -656,6 +657,7 @@ export type ____ImageStyle_Internal = $ReadOnly<{
export type ____DangerouslyImpreciseStyle_InternalCore = $ReadOnly<{
...$Exact<____TextStyle_Internal>,
resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat',
objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down',
tintColor?: ____ColorValue_Internal,
overlayColor?: string,
}>;
Expand Down
49 changes: 49 additions & 0 deletions packages/rn-tester/js/examples/Image/ImageExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,55 @@ exports.examples = [
);
},
},
{
title: 'Object Fit',
description: ('The `objectFit` style prop controls how the image is ' +
'rendered within the frame.': string),
render: function (): React.Node {
return (
<View>
{[smallImage, fullImage].map((image, index) => {
return (
<View key={index}>
<View style={styles.horizontal}>
<View>
<Text style={styles.resizeModeText}>Contain</Text>
<Image
style={[styles.resizeMode, {objectFit: 'contain'}]}
source={image}
/>
</View>
<View style={styles.leftMargin}>
<Text style={styles.resizeModeText}>Cover</Text>
<Image
style={[styles.resizeMode, {objectFit: 'cover'}]}
source={image}
/>
</View>
</View>
<View style={styles.horizontal}>
<View>
<Text style={styles.resizeModeText}>Fill</Text>
<Image
style={[styles.resizeMode, {objectFit: 'fill'}]}
source={image}
/>
</View>
<View style={styles.leftMargin}>
<Text style={styles.resizeModeText}>Scale Down</Text>
<Image
style={[styles.resizeMode, {objectFit: 'scale-down'}]}
source={image}
/>
</View>
</View>
</View>
);
})}
</View>
);
},
},
{
title: 'Resize Mode',
description: ('The `resizeMode` style prop controls how the image is ' +
Expand Down

0 comments on commit b2452ab

Please sign in to comment.