React Native'de dinamik stiller yapabilir miyim?


119

Şöyle bir render içeren bir bileşenim olduğunu varsayalım:

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

JewelStyle = nerede

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

Arka plan rengini nasıl dinamik ve rastgele atayabilirim? denedim

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

Ancak bu, tüm View örneklerinin aynı renge sahip olmasını sağlar, her birinin benzersiz olmasını istiyorum.

Herhangi bir ipucu?

Yanıtlar:


176

Genellikle şu satırlarda bir şeyler yaparım:

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

...

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

Görünüm her oluşturulduğunda, kendisiyle ilişkilendirilmiş rastgele bir renkle yeni bir stil nesnesi somutlaştırılacaktır. Elbette bu, bileşen her yeniden işlendiğinde renklerin değişeceği anlamına gelir, bu belki de istediğiniz şey değildir. Bunun yerine şöyle bir şey yapabilirsiniz:

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

...

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

32
Bu yöntem Stil Sayfalarını hiç kullanmaz. Stylesheet.create()Yine de Stil Sayfalarını ilan edenlerin amacı nedir ?
fatuhoku

2
@fatuhoku, aynı stili birden fazla yerde yeniden kullanmanız gerektiğinde güzel
Bob9630

4
Stylesheet.create kullanmanın mükemmel bir faydası var mı?
Dominic

36
@DominicTobias Stil Sayfası. Paketler oluşturun ve stili yerel bölgeye yalnızca bir kez "gönderin". Bu, aynı stili birden çok kez yeniden kullandığınızda veya aynı bileşeni birden çok kez yüklediğinizde, paketlemek ve yeniden "göndermek" yerine stili yeniden kullanacağı anlamına gelir. Örneğin, 3000 stilize edilmiş satır yüklüyorsanız, performansta önemli bir artış hissedeceksiniz.
sospedra

64

Evet yapabilirsin ve aslında StyleSheet.createstillerinizi yaratmak için kullanmalısınız .

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;

Ve sonra:

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

9
Bu cevap, bir stilin stil sayfasında tanımlandığı, ancak daha sonra bir bileşende geçersiz kılınabileceği iyi bir örneği gösterir
bitler ve

5
AFAIK kullanımı , dokümanlarda belirtildiği gibi StyleSheet.flattenherhangi bir optimizasyonu ortadan StyleSheet.createkaldırır: "NOT: Bunu kötüye kullanmak optimizasyonlar açısından sizi zorlayabileceğinden dikkatli olun. Kimlikler, genel olarak köprü ve bellek yoluyla optimizasyonları etkinleştirir. Stil nesnelerine doğrudan atıfta bulunmak sizi bunlardan mahrum eder bu optimizasyonlar. " ( facebook.github.io/react-native/docs/stylesheet.html ).
gustavopch

27

Hala yararlanmak istiyorsanız StyleSheet.createve dinamik stillere sahipseniz, şunu deneyin:

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

Nasıl Bildirimi stylemalı Viewdinamik stilleri ile stil birleştirir bir dizi olarak ayarlanır.


11

En kolayı benimki:

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

Yayınlanan cevabı @Sarahcartenz yorumuna uymak için düzenledim
Marecky

harika, gerçekten harika. Bu çözümle bir özelliği de geçersiz kılabilirsiniz, değil mi? sonuncusu bir
öncekini

10

Sözdizimsel olarak bazı sorunlar yaşandı. Bu benim için çalıştı

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

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

Teşekkür ederim @Yogesh, tam da aradığım şey bu. Stilleri kullanmak ve buna rağmen ihtiyacım olan şeylere daha fazlasını eklemek istiyorum.
TLee

4

Bunun gibi bir şey isteyeceksiniz:

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

    }
});

Bu örnekte, bileşendeki satırlar için verileri içeren satır dizisini alıyorum ve bunu bir Metin bileşenleri dizisiyle eşleştiriyorum. getRandomColorHer yeni Metin bileşeni oluşturduğumda işlevi çağırmak için satır içi stilleri kullanıyorum .

Kodunuzla ilgili sorun, stili bir kez tanımlamanız ve bu nedenle getRandomColor'un stili tanımladığınızda yalnızca bir kez çağrılmasıdır.


Merhaba Colin, bunun için teşekkürler ama diğer stil parametrelerini aynı anda nasıl geçirebilirim?
Pete Thorne

Style = {{backgroundColor: getRandomColor (), color: 'black'}} gibi mi demek istiyorsunuz?
Colin Ramsay

Teşekkürler, bu işe yarayacak, ancak diğer cevabı da tek seferde bir stil bloğunu nasıl geçirebileceğinizi göstermeye yardımcı olduğu için kabul ettim.
Pete Thorne

2
Aslında diğer cevabın da daha iyi olduğunu düşünüyorum :)
Colin Ramsay

2

Bunun çok geç olduğunu biliyorum, ancak yine de merak eden herkes için kolay bir çözüm.

Stiller için bir dizi oluşturabilirsiniz:

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

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

İkincisi, stil sayfasında belirtildiği gibi herhangi bir orijinal arka plan rengini geçersiz kılar. Ardından rengi değiştiren bir işleve sahip olun:

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

Bu, rastgele bir onaltılık renk oluşturacaktır. Sonra bu işlevi her zaman çağırın ve bam, yeni arka plan rengi.


1

Birkaç cevap olduğunu biliyorum, ama bence en iyisi ve en basit olanı, devletin amacı "Değiştirmek için" durumu kullanmaktır.

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

Durum değerini doğrudan stil nesnesine bağlayabilirsiniz. İşte bir örnek:

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

Evet, dinamik stiller yapabilirsiniz. Değerleri Bileşenlerden geçirebilirsiniz.

Önce StyleSheetFactory.js'yi oluşturun

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

daha sonra bileşeninizde aşağıdaki şekilde kullanın

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

Nesne yayma operatörünü "..." kullanmak benim için çalıştı:

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

0

Örneğin filtreli bir ekran kullanıyorsanız ve seçilip seçilmediğine göre filtrenin arka planını ayarlamak istiyorsanız, şunları yapabilirsiniz:

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

Hangi sette filtre:

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

Not: işlev this.props.setVenueFilter(filters)bir yeniden düzenleme işlemidir ve this.props.venueFiltersbir yeniden düzenleme durumudur.


0

Birisinin koşulları uygulaması gerekmesi durumunda

 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

İşte benim için işe yarayan şey:

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

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

Bazı nedenlerden dolayı, benimkinin düzgün bir şekilde güncellenmesinin tek yolu buydu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.