Permalink
Browse files

Introducing <ImageBackground>, replacement for <Image> which supports…

… 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 9637dd4a1b78d5f6da510b1b4ad10d45d67badbf
@@ -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.

Show comment
Hide comment
@chirag04

chirag04 May 24, 2017

Collaborator

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

@chirag04

chirag04 May 24, 2017

Collaborator

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

This comment has been minimized.

Show comment
Hide comment
@brentvatne

brentvatne May 24, 2017

Collaborator

👍 to @chirag04's point

@brentvatne

brentvatne May 24, 2017

Collaborator

👍 to @chirag04's point

This comment has been minimized.

Show comment
Hide comment
@grabbou

grabbou Jul 5, 2017

Collaborator

I actually never nested inside Image :D

@grabbou

grabbou Jul 5, 2017

Collaborator

I actually never nested inside Image :D

left: 0,
right: 0,
top: 0,
bottom: 0,
}}
/>
{children}
</View>
);
}
}
module.exports = ImageBackground;
@@ -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'); },
@@ -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==';
@@ -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>;
}
});
@@ -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>
);
},
},

12 comments on commit 9637dd4

@Norfeldt

This comment has been minimized.

Show comment
Hide comment
@Norfeldt

Norfeldt Jul 11, 2017

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

Norfeldt replied Jul 11, 2017

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

@fenglu09

This comment has been minimized.

Show comment
Hide comment
@fenglu09

fenglu09 Jul 13, 2017

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

fenglu09 replied Jul 13, 2017

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

@shergin

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Aug 2, 2017

Contributor

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

Contributor

shergin replied Aug 2, 2017

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

@fenglu09

This comment has been minimized.

Show comment
Hide comment
@fenglu09

fenglu09 Aug 2, 2017

Yes. ImageBackground supports imageStyles will be more useful.

fenglu09 replied Aug 2, 2017

Yes. ImageBackground supports imageStyles will be more useful.

@shergin

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Aug 2, 2017

Contributor

@fenglu09 It already does support it!

Contributor

shergin replied Aug 2, 2017

@fenglu09 It already does support it!

@fenglu09

This comment has been minimized.

Show comment
Hide comment
@fenglu09

fenglu09 Aug 2, 2017

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",

fenglu09 replied Aug 2, 2017

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

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Aug 2, 2017

Contributor

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

Contributor

shergin replied Aug 2, 2017

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

@fenglu09

This comment has been minimized.

Show comment
Hide comment
@fenglu09

fenglu09 Aug 2, 2017

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

fenglu09 replied Aug 2, 2017

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

@shergin

This comment has been minimized.

Show comment
Hide comment
@shergin

shergin Aug 2, 2017

Contributor

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

Contributor

shergin replied Aug 2, 2017

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

This comment has been minimized.

Show comment
Hide comment
@moritzschaefer

moritzschaefer Aug 2, 2017

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

moritzschaefer replied Aug 2, 2017

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

@fenglu09

This comment has been minimized.

Show comment
Hide comment
@fenglu09

fenglu09 Aug 3, 2017

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

fenglu09 replied Aug 3, 2017

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

Please sign in to comment.