ฉันสามารถสร้างรูปแบบไดนามิกใน React Native ได้หรือไม่


119

สมมติว่าฉันมีส่วนประกอบที่มีการเรนเดอร์ดังนี้:

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

โดยที่ jewelStyle =

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

ฉันจะสร้างสีพื้นหลังแบบไดนามิกและกำหนดแบบสุ่มได้อย่างไร ฉันพยายามแล้ว

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

แต่สิ่งนี้ทำให้อินสแตนซ์ทั้งหมดของ View มีสีเดียวกันฉันต้องการให้แต่ละอันไม่ซ้ำกัน

เคล็ดลับใด ๆ

คำตอบ:


176

ฉันมักจะทำอะไรบางอย่างตามแนวของ:

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

...

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

ทุกครั้งที่แสดงมุมมองวัตถุรูปแบบใหม่จะถูกสร้างอินสแตนซ์ด้วยสีสุ่มที่เกี่ยวข้อง แน่นอนว่านี่หมายความว่าสีจะเปลี่ยนไปทุกครั้งที่มีการแสดงผลส่วนประกอบใหม่ซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ คุณสามารถทำสิ่งนี้แทนได้:

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

...

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

32
วิธีนี้ไม่ใช้สไตล์ชีทเลย วัตถุประสงค์ของการประกาศสไตล์ชีทเหล่านั้นStylesheet.create()คืออะไร?
fatuhoku

2
@fatuhoku เป็นเรื่องที่ดีสำหรับเมื่อคุณต้องใช้รูปแบบเดิมซ้ำในหลาย ๆ ที่
Bob9630

4
มีประโยชน์มากมายในการใช้ Stylesheet.create หรือไม่?
Dominic

36
@DominicTobias Stylesheet.create packs และ "ส่ง" สไตล์ไปยังโซนเนทีฟเพียงครั้งเดียว ซึ่งหมายความว่าเมื่อคุณใช้รูปแบบเดิมซ้ำหลายครั้งหรือโหลดส่วนประกอบเดียวกันหลาย ๆ ครั้งระบบจะนำสไตล์ดังกล่าวมาใช้ซ้ำแทนการบรรจุและ "ส่ง" อีกครั้ง ตัวอย่างเช่นหากคุณกำลังโหลด 3000 แถวสไตล์คุณจะรู้สึกได้ถึงการเพิ่มประสิทธิภาพอย่างมาก
sospedra

64

ใช่คุณทำได้และจริงๆแล้วคุณควรใช้StyleSheet.createเพื่อสร้างสไตล์ของคุณ

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;

แล้ว:

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

9
คำตอบนี้แสดงตัวอย่างที่ดีที่มีการกำหนดสไตล์ในสไตล์ชีต แต่สามารถแทนที่ได้ในภายหลังในส่วนประกอบ
บิตและ

5
AFAIK โดยใช้StyleSheet.flattenเพียงแค่ทิ้งการเพิ่มประสิทธิภาพจากStyleSheet.createที่ระบุไว้ในเอกสาร: "หมายเหตุ: ใช้ความระมัดระวังเนื่องจากการใช้ในทางที่ผิดอาจทำให้คุณเสียภาษีในแง่ของการเพิ่มประสิทธิภาพ ID เปิดใช้งานการเพิ่มประสิทธิภาพผ่านบริดจ์และหน่วยความจำโดยทั่วไปการอ้างถึงสไตล์ออบเจ็กต์โดยตรงจะทำให้คุณไม่ การเพิ่มประสิทธิภาพเหล่านี้ " ( facebook.github.io/react-native/docs/stylesheet.html )
gustavopch

27

หากคุณยังต้องการใช้ประโยชน์จากStyleSheet.createรูปแบบไดนามิกให้ลองใช้สิ่งนี้:

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

สังเกตว่าstyleคุณสมบัติของการViewตั้งค่าเป็นอาร์เรย์ที่รวมสไตล์ชีตของคุณเข้ากับสไตล์ไดนามิกของคุณอย่างไร


11

ง่ายที่สุดคือของฉัน:

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

ฉันแก้ไขคำตอบที่โพสต์เพื่อให้สอดคล้องกับความคิดเห็นของ
@Sarahcartenz

ยอดเยี่ยมมันยอดเยี่ยมจริงๆ เราสามารถแทนที่คุณสมบัติด้วยโซลูชันนี้ได้ใช่ไหม? สุดท้ายแทนที่ก่อนหน้านี้
โดย

10

มีปัญหาบางอย่างทางวากยสัมพันธ์ สิ่งนี้ได้ผลสำหรับฉัน

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

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

ขอบคุณ @Yogesh นี่คือสิ่งที่ฉันกำลังมองหา ฉันต้องการใช้ประโยชน์จากรูปแบบและยังสามารถเพิ่มเติมในสิ่งที่ฉันต้องการได้
TLee

4

คุณจะต้องการสิ่งนี้:

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

    }
});

ในตัวอย่างนี้ฉันใช้อาร์เรย์แถวที่มีข้อมูลสำหรับแถวในคอมโพเนนต์และแมปลงในอาร์เรย์ของคอมโพเนนต์ข้อความ ฉันใช้รูปแบบอินไลน์เพื่อเรียกไฟล์getRandomColorฟังก์ชันทุกครั้งที่สร้างส่วนประกอบข้อความใหม่

ปัญหาเกี่ยวกับโค้ดของคุณคือคุณกำหนดสไตล์เพียงครั้งเดียวดังนั้น getRandomColor จึงถูกเรียกเพียงครั้งเดียว - เมื่อคุณกำหนดสไตล์


สวัสดีโคลินขอบคุณสำหรับสิ่งนั้น แต่ฉันจะส่งผ่านพารามิเตอร์สไตล์อื่น ๆ ในเวลาเดียวกันได้อย่างไร
Pete Thorne

คุณหมายถึงชอบ style = {{backgroundColor: getRandomColor (), color: 'black'}}?
Colin Ramsay

ขอบคุณนั่นจะได้ผล แต่ฉันยอมรับคำตอบอื่นเพราะมันช่วยแสดงให้เห็นว่าคุณสามารถส่งผ่านบล็อกของสไตล์ต่างๆได้อย่างไรในคราวเดียว
Pete Thorne

2
ฉันคิดว่าคำตอบอื่น ๆ ก็เป็นคำตอบที่ดีกว่าเช่นกัน :)
Colin Ramsay

2

ฉันรู้ว่านี่มันสายไปแล้ว แต่สำหรับใครที่ยังสงสัยนี่เป็นวิธีง่ายๆ

คุณสามารถสร้างอาร์เรย์สำหรับสไตล์:

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

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

ประการที่สองจะแทนที่สีพื้นหลังดั้งเดิมตามที่ระบุไว้ในสไตล์ชีต จากนั้นมีฟังก์ชั่นที่เปลี่ยนสี:

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

สิ่งนี้จะสร้างสีฐานสิบหกแบบสุ่ม จากนั้นเรียกใช้ฟังก์ชันนั้นเมื่อใดก็ได้และแบมแบมสีพื้นหลังใหม่


1

ฉันรู้ว่ามีหลายคำตอบ แต่ฉันคิดว่าสิ่งที่ดีที่สุดและง่ายที่สุดคือการใช้สถานะ "การเปลี่ยนแปลง" คือจุดประสงค์ของรัฐ

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

คุณสามารถผูกค่าสถานะเข้ากับวัตถุสไตล์ได้โดยตรง นี่คือตัวอย่าง:

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

ใช่คุณสามารถสร้างรูปแบบไดนามิกได้ คุณสามารถส่งผ่านค่าจากส่วนประกอบ

สร้าง 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,
      }
    })
  }
}

จากนั้นใช้ในส่วนประกอบของคุณต่อไปนี้

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

การใช้ตัวดำเนินการกระจายวัตถุ "... " ได้ผลสำหรับฉัน:

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

0

หากคุณกำลังใช้หน้าจอที่มีตัวกรองเป็นต้นและคุณต้องการตั้งค่าพื้นหลังของตัวกรองว่าถูกเลือกหรือไม่คุณสามารถทำได้:

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

ตัวกรองชุดใดคือ:

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: ฟังก์ชันthis.props.setVenueFilter(filters)นี้เป็นการกระทำซ้ำซ้อนและthis.props.venueFiltersเป็นสถานะ redux


0

ในกรณีที่มีคนต้องการใช้เงื่อนไข

 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

นี่คือสิ่งที่ใช้ได้ผลสำหรับฉัน:

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

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

ด้วยเหตุผลบางประการนี่เป็นวิธีเดียวที่ฉันจะอัปเดตได้อย่างถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.