Puis-je créer des styles dynamiques dans React Native?

119

Disons que j'ai un composant avec un rendu comme celui-ci:

<View style={jewelStyle}></View>

Où jewelStyle =

  {
    borderRadius: 10,
    backgroundColor: '#FFEFCC',
    width: 20,
    height: 20,
  },

Comment puis-je rendre la couleur d'arrière-plan dynamique et assignée au hasard? J'ai essayé

  {
    borderRadius: 10,
    backgroundColor: getRandomColor(),
    width: 20,
    height: 20,
  },

Mais cela fait que toutes les instances de View ont la même couleur, je veux que chacune soit unique.

Des conseils?

Pete Thorne
la source

Réponses:

176

Je fais généralement quelque chose du genre:

<View style={this.jewelStyle()} />

...

jewelStyle = function(options) {
   return {
     borderRadius: 12,
     background: randomColor(),
   }
 }

Chaque fois que View est rendu, un nouvel objet de style sera instancié avec une couleur aléatoire qui lui est associée. Bien sûr, cela signifie que les couleurs changeront à chaque fois que le composant est re-rendu, ce qui n'est peut-être pas ce que vous voulez. Au lieu de cela, vous pouvez faire quelque chose comme ceci:

var myColor = randomColor()
<View style={jewelStyle(myColor)} />

...

jewelStyle = function(myColor) {
   return {
     borderRadius: 10,
     background: myColor,
   }
 }
Jimmie Berg
la source
32
Cette méthode n'utilise pas du tout les feuilles de style. Quel est le but de ces déclarations de feuilles de style avec de Stylesheet.create()toute façon?
fatuhoku
2
@fatuhoku c'est bien quand vous avez besoin de réutiliser le même style à plusieurs endroits
Bob9630
4
y a-t-il un grand avantage à utiliser Stylesheet.create?
Dominic
36
@DominicTobias Stylesheet.create emballe et "envoie" le style à la zone native une seule fois. Ce qui signifie que lorsque vous réutilisez le même style plusieurs fois, ou que vous chargez le même composant plusieurs fois, cela va réutiliser le style au lieu de le compresser et de «renvoyer» à nouveau. Par exemple, si vous chargez un style de 3000 lignes, vous ressentirez une augmentation considérable des performances.
sospedra
64

Oui, vous pouvez et en fait, vous devriez utiliser StyleSheet.createpour créer vos styles.

import React, { Component } from 'react';
import {
    StyleSheet,
    Text,
    View
} from 'react-native';    

class Header extends Component {
    constructor(props){
        super(props);
    }    

    render() {
        const { title, style } = this.props;
        const { header, text } = defaultStyle;
        const combineStyles = StyleSheet.flatten([header, style]);    

        return (
            <View style={ combineStyles }>
                <Text style={ text }>
                    { title }
                </Text>
            </View>
        );
    }
}    

const defaultStyle = StyleSheet.create({
    header: {
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#fff',
        height: 60,
        paddingTop: 15,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 3 },
        shadowOpacity: 0.4,
        elevation: 2,
        position: 'relative'
    },
    text: {
        color: '#0d4220',
        fontSize: 16
    }
});    

export default Header;

Puis:

<Header title="HOME" style={ {backgroundColor: '#10f1f0'} } />
diégoprates
la source
9
Cette réponse montre un bon exemple où un style est défini dans la feuille de style, mais peut être remplacé plus tard dans un composant
bits et
5
L'utilisation d'AFAIK StyleSheet.flattenjette simplement toute optimisation StyleSheet.createcomme indiqué dans la documentation: "REMARQUE: soyez prudent, car abuser de cela peut vous taxer en termes d'optimisations. Les ID permettent des optimisations via le pont et la mémoire en général. Se référer directement aux objets de style vous privera de ces optimisations. " ( facebook.github.io/react-native/docs/stylesheet.html ).
gustavopch
27

Si vous souhaitez toujours profiter StyleSheet.createet avoir des styles dynamiques, essayez ceci:

const Circle = ({initial}) => {


const initial = user.pending ? user.email[0] : user.firstName[0];

    const colorStyles = {
        backgroundColor: randomColor()
    };

    return (
        <View style={[styles.circle, colorStyles]}>
            <Text style={styles.text}>{initial.toUpperCase()}</Text>
        </View>
    );
};

const styles = StyleSheet.create({
    circle: {
        height: 40,
        width: 40,
        borderRadius: 30,
        overflow: 'hidden'
    },
    text: {
        fontSize: 12,
        lineHeight: 40,
        color: '#fff',
        textAlign: 'center'
    }
});

Remarquez comment la stylepropriété de Viewest définie comme un tableau qui combine votre feuille de style avec vos styles dynamiques.

Carlos Atencio
la source
11

Le plus simple est le mien:

<TextInput
  style={[
    styles.default,
    this.props.singleSourceOfTruth ?
    { backgroundColor: 'black' } 
    : { backgroundColor: 'white' }
]}/>
Il pleut
la source
J'ai modifié la réponse publiée pour me conformer au commentaire de
@Sarahcartenz
merveilleux, c'est vraiment génial. On peut également remplacer une propriété avec cette solution, non? les derniers écrase le précédent
besil
10

Eu un problème de syntaxe. Cela a fonctionné pour moi

<Text style={[styles.textStyle,{color: 'red'}]}> Hello </Text>

const styles = StyleSheet.create({
   textStyle :{
      textAlign: 'center',   
      fontFamily: 'Arial',
      fontSize: 16
  }
  });
Yogesh Lolusare
la source
Merci @Yogesh, c'est exactement ce que je recherche. Je veux utiliser des styles et pourtant pouvoir y ajouter plus de choses dont j'avais besoin.
TLee
4

Vous voudrez quelque chose comme ça:

var RandomBgApp = React.createClass({
    render: function() {

        var getRandomColor = function() {
            var letters = '0123456789ABCDEF'.split('');
            var color = '#';
            for (var i = 0; i < 6; i++ ) {
                color += letters[Math.floor(Math.random() * 16)];
            }
            return color;
        };

        var rows = [
            { name: 'row 1'},
            { name: 'row 2'},
            { name: 'row 3'}
        ];

        var rowNodes = rows.map(function(row) {
            return <Text style={{backgroundColor:getRandomColor()}}>{row.name}</Text>
        });

        return (
            <View>
                {rowNodes}
            </View>
        );

    }
});

Dans cet exemple, je prends le tableau de lignes, contenant les données pour les lignes du composant, et je le mappe dans un tableau de composants de texte. J'utilise des styles en ligne pour appeler la getRandomColorfonction chaque fois que je crée un nouveau composant Texte.

Le problème avec votre code est que vous définissez le style une fois et donc getRandomColor n'est appelé qu'une seule fois - lorsque vous définissez le style.

Colin Ramsay
la source
Salut Colin, merci pour cela, mais comment puis-je passer les autres paramètres de style en même temps?
Pete Thorne
Vous voulez dire comme style = {{backgroundColor: getRandomColor (), color: 'black'}}?
Colin Ramsay
Merci, cela fonctionnera, mais j'ai accepté l'autre réponse car elle montre comment vous pouvez transmettre un bloc de styles en une seule fois.
Pete Thorne
2
Je pense en fait que l'autre réponse était la meilleure aussi :)
Colin Ramsay
2

Je sais que c'est extrêmement tard, mais pour quiconque se demande encore, voici une solution facile.

Vous pouvez simplement créer un tableau pour les styles:

this.state ={
   color: "#fff"
}

style={[
  styles.jewelstyle, {
  backgroundColor: this.state.BGcolor
}

Le second remplacera toute couleur d'arrière-plan d'origine comme indiqué dans la feuille de style. Ensuite, ayez une fonction qui change la couleur:

generateNewColor(){
  var randomColor = '#'+Math.floor(Math.random()*16777215).toString(16);
  this.setState({BGcolor: randomColor})
}

Cela générera une couleur hexadécimale aléatoire. Ensuite, appelez simplement cette fonction à chaque fois et bam, nouvelle couleur de fond.

Max Gertner
la source
1

Je sais qu'il y a plusieurs réponses, mais je pense que la meilleure et la plus simple est d'utiliser un état "Changer" est le but de l'état.

export default class App extends Component {
    constructor(props) {
      super(props);
      this.state = {
          style: {
              backgroundColor: "white"
          }
      };
    }
    onPress = function() {
      this.setState({style: {backgroundColor: "red"}});
    }
    render() {
       return (
          ...
          <View style={this.state.style}></View>
          ...
       )
    }

}

Cesar Alonso
la source
1

Vous pouvez lier la valeur d'état directement à l'objet de style. Voici un exemple:

class Timer extends Component{
 constructor(props){
 super(props);
 this.state = {timer: 0, color: '#FF0000'};
 setInterval(() => {
   this.setState({timer: this.state.timer + 1, color: this.state.timer % 2 == 0 ? '#FF0000' : '#0000FF'});
 }, 1000);
}

render(){
 return (
   <View>

    <Text>Timer:</Text>
    <Text style={{backgroundColor: this.state.color}}>{this.state.timer}</Text>
  </View>
 );
 }
}
Hossam Ghareeb
la source
1

Oui, vous pouvez créer des styles dynamiques. Vous pouvez transmettre des valeurs à partir des composants.

Créez d'abord StyleSheetFactory.js

import { StyleSheet } from "react-native";
export default class StyleSheetFactory {
  static getSheet(backColor) {
    return StyleSheet.create({
      jewelStyle: {
        borderRadius: 10,
        backgroundColor: backColor,
        width: 20,
        height: 20,
      }
    })
  }
}

puis utilisez-le dans votre composant de la manière suivante

import React from "react";
import { View } from "react-native";
import StyleSheetFactory from './StyleSheetFactory'
class Main extends React.Component {
  getRandomColor = () => {
    var letters = "0123456789ABCDEF";
    var color = "#";
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
  };

  render() {
    return (
      <View>
        <View
          style={StyleSheetFactory.getSheet(this.getRandomColor()).jewelStyle}
        />
        <View
          style={StyleSheetFactory.getSheet(this.getRandomColor()).jewelStyle}
        />
        <View
          style={StyleSheetFactory.getSheet(this.getRandomColor()).jewelStyle}
        />
      </View>
    );
  }
}
Rajesh Nasit
la source
1

L'utilisation de l'opérateur de propagation d'objets "..." a fonctionné pour moi:

<View style={{...jewelStyle, ...{'backgroundColor': getRandomColor()}}}></View>
Cem Roso
la source
0

Si vous utilisez un écran avec des filtres par exemple, et que vous souhaitez définir l'arrière-plan du filtre selon s'il a été sélectionné ou non, vous pouvez faire:

<TouchableOpacity style={this.props.venueFilters.includes('Bar')?styles.filterBtnActive:styles.filterBtn} onPress={()=>this.setFilter('Bar')}>
<Text numberOfLines={1}>
Bar
</Text>
</TouchableOpacity>

Sur quel filtre défini est:

setVenueFilter(filter){
  var filters = this.props.venueFilters;
  filters.push(filter);
  console.log(filters.includes('Bar'), "Inclui Bar");
  this.setState(previousState => {
    return { updateFilter: !previousState.updateFilter };
  });
  this.props.setVenueFilter(filters);
}

PS: la fonction this.props.setVenueFilter(filters)est une action redux, et this.props.venueFiltersest un état redux.

FrikLima
la source
0

Au cas où quelqu'un aurait besoin d'appliquer des conditions

 selectedMenuUI = function(value) {
       if(value==this.state.selectedMenu){
           return {
                flexDirection: 'row',
                alignItems: 'center',
                paddingHorizontal: 20,
                paddingVertical: 10,
                backgroundColor: 'rgba(255,255,255,0.3)', 
                borderRadius: 5
           }  
       } 
       return {
            flexDirection: 'row',
            alignItems: 'center',
            paddingHorizontal: 20,
            paddingVertical: 10
       }
    }
Shankey
la source
0

Voici ce qui a fonctionné pour moi:

render() {
  const { styleValue } = this.props;
  const dynamicStyleUpdatedFromProps = {
    height: styleValue,
    width: styleValue,
    borderRadius: styleValue,
  }

  return (
    <View style={{ ...styles.staticStyleCreatedFromStyleSheet, ...dynamicStyleUpdatedFromProps }} />
  );
}

Pour une raison quelconque, c'était la seule façon dont le mien se mettrait à jour correctement.

Daltron
la source