Bisakah saya membuat gaya dinamis di React Native?

119

Katakanlah saya memiliki komponen dengan render seperti ini:

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

Di mana permataStyle =

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

Bagaimana saya bisa membuat warna latar belakang dinamis dan ditetapkan secara acak? Saya sudah mencoba

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

Tapi ini membuat semua tampilan memiliki warna yang sama, saya ingin masing-masing unik.

Ada tips?

Pete Thorne
sumber

Jawaban:

176

Saya biasanya melakukan sesuatu di sepanjang baris:

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

...

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

Setiap kali View dirender, objek gaya baru akan dibuat dengan warna acak yang terkait dengannya. Tentu saja, ini berarti warna akan berubah setiap kali komponen dirender ulang, yang mungkin bukan yang Anda inginkan. Sebaliknya, Anda dapat melakukan sesuatu seperti ini:

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

...

jewelStyle = function(myColor) {
   return {
     borderRadius: 10,
     background: myColor,
   }
 }
Jimmie Berg
sumber
32
Metode ini sama sekali tidak menggunakan Stylesheets. Apa tujuan dari mereka mendeklarasikan Stylesheets Stylesheet.create()?
fatuhoku
2
@fatuhoku itu bagus ketika Anda perlu menggunakan kembali gaya yang sama di banyak tempat
Bob9630
4
apakah ada banyak manfaat kinerja menggunakan Stylesheet.create?
Dominic
36
@DominicTobias Stylesheet.create mengemas dan "mengirim" gaya ke zona asli hanya sekali. Artinya, saat Anda menggunakan kembali gaya yang sama beberapa kali, atau memuat komponen yang sama beberapa kali, ia akan menggunakan kembali gaya tersebut, bukan mengemas dan "mengirim" lagi. Misalnya, jika Anda memuat 3000 baris bergaya, Anda akan merasakan peningkatan kinerja yang cukup besar.
sospedra
64

Ya, Anda bisa dan sebenarnya, Anda harus menggunakan StyleSheet.createuntuk membuat gaya Anda.

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;

Lalu:

<Header title="HOME" style={ {backgroundColor: '#10f1f0'} } />
diegoprates
sumber
9
Jawaban ini menunjukkan contoh yang baik di mana sebuah gaya didefinisikan di stylesheet, tetapi dapat diganti nanti dalam sebuah komponen
bitsand
5
Penggunaan AFAIK StyleSheet.flattenhanya membuang pengoptimalan apa pun dari StyleSheet.createseperti yang dinyatakan dalam dokumen: "CATATAN: Berhati-hatilah karena menyalahgunakan ini dapat membebani Anda dalam hal pengoptimalan. ID mengaktifkan pengoptimalan melalui bridge dan memori secara umum. Mengacu ke objek gaya secara langsung akan membuat Anda kehilangan pengoptimalan ini. " ( facebook.github.io/react-native/docs/stylesheet.html ).
gustavopch
27

Jika Anda masih ingin memanfaatkan StyleSheet.createdan juga memiliki gaya dinamis, cobalah ini:

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

Perhatikan bagaimana styleproperti dari Viewdisetel sebagai larik yang menggabungkan lembar gaya Anda dengan gaya dinamis Anda.

Carlos Atencio
sumber
11

Yang termudah adalah milik saya:

<TextInput
  style={[
    styles.default,
    this.props.singleSourceOfTruth ?
    { backgroundColor: 'black' } 
    : { backgroundColor: 'white' }
]}/>
Hujan
sumber
Saya mengedit memposting jawaban untuk mematuhi komentar
@Sarahcartenz
luar biasa, itu memang luar biasa. Anda juga dapat mengganti properti dengan solusi ini, bukan? yang terakhir menimpa yang sebelumnya
besil
10

Memiliki beberapa masalah secara sintaksis. Ini berhasil untuk saya

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

const styles = StyleSheet.create({
   textStyle :{
      textAlign: 'center',   
      fontFamily: 'Arial',
      fontSize: 16
  }
  });
Yogesh Lolusare
sumber
Terima kasih @Yogesh, inilah yang saya cari. Saya ingin menggunakan gaya, namun dapat menambahkan lebih banyak pada hal-hal yang saya butuhkan.
TLee
4

Anda akan menginginkan sesuatu seperti ini:

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

    }
});

Dalam contoh ini saya mengambil array baris, yang berisi data untuk baris dalam komponen, dan memetakannya ke dalam array komponen Teks. Saya menggunakan gaya sebaris untuk memanggil getRandomColorfungsi setiap kali saya membuat komponen Teks baru.

Masalah dengan kode Anda adalah Anda mendefinisikan gaya satu kali dan oleh karena itu getRandomColor hanya dipanggil sekali - saat Anda menentukan gaya.

Colin Ramsay
sumber
Hai Colin, terima kasih untuk itu, tetapi bagaimana saya bisa meneruskan parameter gaya lain pada saat yang bersamaan?
Pete Thorne
Maksud Anda seperti style = {{backgroundColor: getRandomColor (), color: 'black'}}?
Colin Ramsay
Terima kasih, itu akan berhasil tetapi saya telah menerima jawaban lain karena ini membantu menunjukkan bagaimana Anda dapat melewati sekumpulan gaya sekaligus.
Pete Thorne
2
Saya pikir jawaban yang lain juga lebih baik :)
Colin Ramsay
2

Saya tahu ini sudah sangat terlambat, tetapi bagi siapa pun yang masih bertanya-tanya, inilah solusi mudah.

Anda bisa membuat array untuk gaya:

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

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

Yang kedua akan menimpa warna latar belakang asli seperti yang dinyatakan dalam lembar gaya. Kemudian ada fungsi yang mengubah warna:

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

Ini akan menghasilkan warna hex acak. Kemudian panggil saja fungsi itu kapan saja dan bam, warna latar belakang baru.

Max Gertner
sumber
1

Saya tahu ada beberapa jawaban, tapi menurut saya yang terbaik dan paling sederhana adalah menggunakan keadaan "Untuk berubah" adalah tujuan negara.

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
sumber
1

Anda dapat mengikat nilai status secara langsung ke objek gaya. Berikut ini contohnya:

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
sumber
1

Ya, Anda bisa membuat gaya dinamis. Anda dapat meneruskan nilai dari Komponen.

Pertama buat 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,
      }
    })
  }
}

kemudian gunakan dalam komponen Anda dengan cara berikut

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
sumber
1

Menggunakan operator penyebaran objek "..." berhasil untuk saya:

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

Jika Anda menggunakan layar dengan filter misalnya, dan Anda ingin mengatur latar belakang filter apakah sudah dipilih atau tidak, Anda dapat melakukan:

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

Di set filter mana adalah:

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: fungsinya this.props.setVenueFilter(filters)adalah aksi redux, dan this.props.venueFiltersmerupakan status redux.

FrikLima
sumber
0

Jika seseorang perlu menerapkan ketentuan

 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
sumber
0

Inilah yang berhasil untuk saya:

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

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

Untuk beberapa alasan, ini adalah satu-satunya cara saya memperbarui dengan benar.

Daltron
sumber