Kann ich in React Native dynamische Stile erstellen?


119

Angenommen, ich habe eine Komponente mit einem Render wie diesem:

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

Wo juwelStyle =

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

Wie kann ich die Hintergrundfarbe dynamisch und zufällig zuordnen? ich habe es versucht

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

Dadurch haben alle Instanzen von View dieselbe Farbe. Ich möchte, dass jede Instanz einzigartig ist.

Irgendwelche Tipps?

Antworten:


176

Normalerweise mache ich etwas in der Art von:

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

...

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

Jedes Mal, wenn die Ansicht gerendert wird, wird ein neues Stilobjekt mit einer zufälligen Farbe instanziiert. Dies bedeutet natürlich, dass sich die Farben jedes Mal ändern, wenn die Komponente neu gerendert wird, was möglicherweise nicht das ist, was Sie wollen. Stattdessen könnten Sie so etwas tun:

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

...

jewelStyle = function(myColor) {
   return {
     borderRadius: 10,
     background: myColor,
   }
 }

32
Diese Methode verwendet überhaupt keine Stylesheets. Was ist der Zweck dieser deklarierten Stylesheets überhaupt Stylesheet.create()?
Fatuhoku

2
@ Fatuhoku ist es schön, wenn Sie den gleichen Stil an mehreren Stellen
wiederverwenden müssen

4
Gibt es einen großen Vorteil bei der Verwendung von Stylesheet.create?
Dominic

35
@DominicTobias Stylesheet.create Packs und "senden" Sie den Stil nur einmal an die native Zone. Das heißt, wenn Sie denselben Stil mehrmals wiederverwenden oder dieselbe Komponente mehrmals laden, wird der Stil wiederverwendet, anstatt ihn zu packen und erneut zu "senden". Wenn Sie beispielsweise 3000 gestylte Reihen laden, spüren Sie einen erheblichen Leistungsschub.
Sospedra

64

Ja, Sie können und sollten Sie tatsächlich verwenden StyleSheet.create, um Ihre Stile zu erstellen.

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;

Und dann:

<Header title="HOME" style={ {backgroundColor: '#10f1f0'} } />

9
Diese Antwort zeigt ein gutes Beispiel, in dem ein Stil im Stylesheet definiert ist, aber später in einer Komponente überschrieben werden kann
Bits und

5
AFAIK verwendet StyleSheet.flattennur die Optimierung, StyleSheet.createwie in den Dokumenten angegeben: "HINWEIS: Seien Sie vorsichtig, da ein Missbrauch dies in Bezug auf Optimierungen belasten kann. IDs ermöglichen Optimierungen über die Brücke und den Speicher im Allgemeinen. Wenn Sie direkt auf Stilobjekte verweisen, werden Sie davon abgehalten." diese Optimierungen. " ( facebook.github.io/react-native/docs/stylesheet.html ).
Gustavopch

27

Wenn Sie dennoch StyleSheet.createdynamische Stile nutzen möchten und diese auch haben möchten , probieren Sie Folgendes aus:

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'
    }
});

Beachten Sie, wie die styleEigenschaft von Viewals Array festgelegt wird, das Ihr Stylesheet mit Ihren dynamischen Styles kombiniert.


11

Das einfachste ist meins:

<TextInput
  style={[
    styles.default,
    this.props.singleSourceOfTruth ?
    { backgroundColor: 'black' } 
    : { backgroundColor: 'white' }
]}/>

Ich habe die gepostete Antwort bearbeitet, um dem Kommentar von
@Sarahcartenz

wunderbar, es ist in der Tat großartig. Mit dieser Lösung kann man auch eine Eigenschaft überschreiben, oder? der letzte überschreibt den vorherigen
bis zum

10

Hatte syntaktisch ein Problem. Das hat bei mir funktioniert

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

const styles = StyleSheet.create({
   textStyle :{
      textAlign: 'center',   
      fontFamily: 'Arial',
      fontSize: 16
  }
  });

Danke @Yogesh, genau das suche ich. Ich möchte Stile verwenden und dennoch mehr zu den Dingen hinzufügen können, die ich brauchte.
TLee

4

Du wirst so etwas wollen:

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>
        );

    }
});

In diesem Beispiel nehme ich das Zeilenarray, das die Daten für die Zeilen in der Komponente enthält, und ordne es einem Array von Textkomponenten zu. Ich verwende Inline-Stile, um die getRandomColorFunktion jedes Mal aufzurufen, wenn ich eine neue Textkomponente erstelle.

Das Problem mit Ihrem Code ist, dass Sie den Stil einmal definieren und getRandomColor daher nur einmal aufgerufen wird - wenn Sie den Stil definieren.


Hallo Colin, danke dafür, aber wie kann ich die anderen Stilparameter gleichzeitig übergeben?
Pete Thorne

Du meinst wie style = {{backgroundColor: getRandomColor (), color: 'black'}}?
Colin Ramsay

Danke, das wird funktionieren, aber ich habe die andere Antwort akzeptiert, da sie zeigt, wie Sie einen Stilblock auf einmal durchlaufen können.
Pete Thorne

2
Ich denke tatsächlich, dass die andere Antwort auch die bessere war :)
Colin Ramsay

2

Ich weiß, dass dies extrem spät ist, aber für alle, die sich noch fragen, ist hier eine einfache Lösung.

Sie können einfach ein Array für die Stile erstellen:

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

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

Die zweite Option überschreibt alle ursprünglichen Hintergrundfarben, wie im Stylesheet angegeben. Dann haben Sie eine Funktion, die die Farbe ändert:

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

Dies erzeugt eine zufällige Hex-Farbe. Rufen Sie dann einfach diese Funktion auf, wann immer und bam, neue Hintergrundfarbe.


1

Ich weiß, dass es mehrere Antworten gibt, aber ich denke, das Beste und Einfachste ist die Verwendung eines Status. "Ändern" ist der Statuszweck.

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>
          ...
       )
    }

}}


1

Sie können den Statuswert direkt an das Stilobjekt binden. Hier ist ein Beispiel:

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>
 );
 }
}

1

Ja, Sie können dynamische Stile erstellen. Sie können Werte von Komponenten übergeben.

Erstellen Sie zuerst 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,
      }
    })
  }
}

Verwenden Sie es dann wie folgt in Ihrer Komponente

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>
    );
  }
}

1

Die Verwendung des Objektverbreitungsoperators "..." hat bei mir funktioniert:

<View style={{...jewelStyle, ...{'backgroundColor': getRandomColor()}}}></View>

0

Wenn Sie beispielsweise einen Bildschirm mit Filtern verwenden und den Hintergrund des Filters festlegen möchten, ob er ausgewählt wurde oder nicht, können Sie Folgendes tun:

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

Auf welchem ​​eingestellten Filter befindet sich:

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: Die Funktion this.props.setVenueFilter(filters)ist eine Redux-Aktion und this.props.venueFiltersein Redux-Zustand.


0

Für den Fall, dass jemand Bedingungen anwenden muss

 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
       }
    }

0

Folgendes hat bei mir funktioniert:

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

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

Aus irgendeinem Grund war dies die einzige Möglichkeit, meine ordnungsgemäß zu aktualisieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.