Skip to content

Commit

Permalink
Introducing <ImageBackground>, replacement for <Image> which supports…
Browse files Browse the repository at this point in the history
… nesting views

Summary:
We are removing support of nesting views inside <Image> component. We decided to do this because having this feature makes supporting `intrinsinc content size` of the `<Image>` impossible; so when the transition process is complete, there will be no need to specify image size explicitly, it can be inferred from actual image bitmap.

And this is the step #0.

<ImageBackground> is very simple drop-in replacement which implements this functionality via very simple styling.
Please, use <ImageBackground> instead of <Image> if you want to put something inside.

Reviewed By: yungsters

Differential Revision: D5100021

fbshipit-source-id: 640c0fb2d1066e166d974efba39b4cfaaee7dd45
  • Loading branch information
shergin authored and facebook-github-bot committed May 24, 2017
1 parent 275ba31 commit 9637dd4
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 4 deletions.
64 changes: 64 additions & 0 deletions Libraries/Image/ImageBackground.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ImageBackground
* @flow
* @format
*/
'use strict';

const Image = require('Image');
const React = require('React');
const View = require('View');

/**
* Very simple drop-in replacement for <Image> which supports nesting views.
*
* ```ReactNativeWebPlayer
* import React, { Component } from 'react';
* import { AppRegistry, View, ImageBackground, Text } from 'react-native';
*
* class DisplayAnImageBackground extends Component {
* render() {
* return (
* <ImageBackground
* style={{width: 50, height: 50}}
* source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
* >
* <Text>React</Text>
* </ImageBackground>
* );
* }
* }
*
* // App registration and rendering
* AppRegistry.registerComponent('DisplayAnImageBackground', () => DisplayAnImageBackground);
* ```
*/
class ImageBackground extends React.Component {
render() {
const {children, style, ...props} = this.props;
return (
<View style={style}>
<Image
{...props}
style={{
position: 'absolute',

This comment has been minimized.

Copy link
@chirag04

chirag04 May 24, 2017

Contributor

i wish this was outside core. It's trivial enough to be an independent module outside core.

This comment has been minimized.

Copy link
@brentvatne

brentvatne May 24, 2017

Collaborator

👍 to @chirag04's point

This comment has been minimized.

Copy link
@grabbou

grabbou Jul 5, 2017

Contributor

I actually never nested inside Image :D

left: 0,
right: 0,
top: 0,
bottom: 0,
}}
/>
{children}
</View>
);
}
}

module.exports = ImageBackground;
1 change: 1 addition & 0 deletions Libraries/react-native/react-native-implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const ReactNative = {
get DrawerLayoutAndroid() { return require('DrawerLayoutAndroid'); },
get FlatList() { return require('FlatList'); },
get Image() { return require('Image'); },
get ImageBackground() { return require('ImageBackground'); },
get ImageEditor() { return require('ImageEditor'); },
get ImageStore() { return require('ImageStore'); },
get KeyboardAvoidingView() { return require('KeyboardAvoidingView'); },
Expand Down
9 changes: 5 additions & 4 deletions RNTester/js/ImageExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var {
StyleSheet,
Text,
View,
ImageBackground,
} = ReactNative;

var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
Expand Down Expand Up @@ -117,15 +118,15 @@ var NetworkImageExample = React.createClass({
</View> : null;
return this.state.error ?
<Text>{this.state.error}</Text> :
<Image
<ImageBackground
source={this.props.source}
style={[styles.base, {overflow: 'visible'}]}
onLoadStart={(e) => this.setState({loading: true})}
onError={(e) => this.setState({error: e.nativeEvent.error, loading: false})}
onProgress={(e) => this.setState({progress: Math.round(100 * e.nativeEvent.loaded / e.nativeEvent.total)})}
onLoad={() => this.setState({loading: false, error: false})}>
{loader}
</Image>;
</ImageBackground>;
}
});

Expand Down Expand Up @@ -436,13 +437,13 @@ exports.examples = [
title: 'Nesting',
render: function() {
return (
<Image
<ImageBackground
style={{width: 60, height: 60, backgroundColor: 'transparent'}}
source={fullImage}>
<Text style={styles.nestedText}>
React
</Text>
</Image>
</ImageBackground>
);
},
},
Expand Down

12 comments on commit 9637dd4

@Norfeldt
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View don't have 'resizeMode' and you can only pass down a style to the View and not the Image.

@fenglu09
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ImageBackground component supports 'resizeMode', it will be more useful.

@shergin
Copy link
Contributor Author

@shergin shergin commented on 9637dd4 Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Norfeldt @fenglu09 ImageBackground supports imageStyles, so resizeMode can be specified. Right?

@fenglu09
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. ImageBackground supports imageStyles will be more useful.

@shergin
Copy link
Contributor Author

@shergin shergin commented on 9637dd4 Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fenglu09 It already does support it!

@fenglu09
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not working for me. It will show warning.
mycode:

<ImageBackground style={styles.backgroundImage} source={require('./img/run_status_block_bg.png')}>
</ImageBackground>
 backgroundImage: {
        flex: 1,
        height: null,
        width: null,
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        resizeMode: 'cover',
        zIndex: -1,
    }

image

react-native version:
"react": "16.0.0-alpha.12",
"react-native": "^0.46.1",

@shergin
Copy link
Contributor Author

@shergin shergin commented on 9637dd4 Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use <ImageBackground imageStyle={{resizeMode: "cover"}}></ImageBackground> or even better (if it works) <ImageBackground resizeMode="cover"></ImageBackground>.

@fenglu09
Copy link

@fenglu09 fenglu09 commented on 9637dd4 Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both imageStyle={{resizeMode: "cover"}} and resizeMode="cover" doesn't wok.
Is there any doc about ImageBackground?

@sibelius
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shergin
Copy link
Contributor Author

@shergin shergin commented on 9637dd4 Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried it on master?
ImageBackground has pretty trivial implementation, so you can use it as a documentation:
https://github.com/facebook/react-native/blob/master/Libraries/Image/ImageBackground.js

@moritzschaefer
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here imageStyle={{resizeMode: "cover"}} doesn't have any effect. My local version of ImageBackground.js does use the imageStyle property

@fenglu09
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shergin
Works fine in react-native: 0.47.1. Thanks

Please sign in to comment.