Tôi có thể tạo kiểu động trong React Native không?


119

Giả sử tôi có một thành phần với kết xuất như thế này:

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

Nơi ngọc trai =

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

Làm cách nào để tạo màu nền động và được gán ngẫu nhiên? Tôi đã thử

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

Nhưng điều này làm cho tất cả các phiên bản của View có cùng màu, tôi muốn mỗi phiên bản là duy nhất.

Bất kỳ lời khuyên?

Câu trả lời:


176

Tôi thường làm điều gì đó dọc theo dòng:

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

...

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

Mỗi khi Chế độ xem được hiển thị, một đối tượng kiểu mới sẽ được khởi tạo với một màu ngẫu nhiên được kết hợp với nó. Tất nhiên, điều này có nghĩa là màu sắc sẽ thay đổi mỗi khi thành phần được kết xuất lại, điều này có lẽ không như bạn muốn. Thay vào đó, bạn có thể làm điều gì đó như sau:

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

...

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

32
Phương pháp này hoàn toàn không sử dụng Biểu định kiểu. Mục đích của việc khai báo Biểu định kiểu là Stylesheet.create()gì?
fatuhoku

2
@fatuhoku nó đẹp để khi bạn cần để tái sử dụng phong cách giống nhau ở nhiều nơi
Bob9630

4
có nhiều lợi ích khi sử dụng Stylesheet.create không?
Dominic

35
@DominicTobias Stylesheet.create gói và "gửi" kiểu đến vùng gốc chỉ một lần. Điều đó có nghĩa là khi bạn sử dụng lại cùng một kiểu nhiều lần hoặc tải cùng một thành phần nhiều lần, nó sẽ sử dụng lại kiểu đó thay vì đóng gói và "gửi" lại. Ví dụ: nếu bạn đang tải 3000 hàng được tạo kiểu, bạn sẽ cảm thấy hiệu suất tăng đáng kể.
sospedra

64

Có, bạn có thể và thực sự, bạn nên sử dụng StyleSheet.createđể tạo phong cách của mình.

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;

Và sau đó:

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

9
Câu trả lời này cho thấy một ví dụ điển hình trong đó một kiểu được xác định trong biểu định kiểu, nhưng có thể bị ghi đè sau đó trong một thành phần
bit và

5
AFAIK StyleSheet.flattenchỉ sử dụng loại bỏ bất kỳ tối ưu hóa nào StyleSheet.createnhư đã nêu trong tài liệu: "LƯU Ý: Hãy thận trọng vì lạm dụng điều này có thể đánh thuế bạn về mặt tối ưu hóa. Các ID cho phép tối ưu hóa thông qua cầu nối và bộ nhớ nói chung. Tham khảo trực tiếp các đối tượng kiểu sẽ tước đi của bạn những tối ưu hóa này. " ( facebook.github.io/react-native/docs/stylesheet.html ).
gustavopch

27

Nếu bạn vẫn muốn tận dụng StyleSheet.createvà cũng có phong cách năng động, hãy thử cách này:

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

Lưu ý cách thuộc styletính của thuộc tính Viewnày được đặt thành một mảng kết hợp biểu định kiểu với các kiểu động của bạn.


11

Dễ nhất là của tôi:

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

Tôi được chỉnh sửa gửi câu trả lời cho phù hợp với @Sarahcartenz bình luận
Marecky

tuyệt vời, nó thực sự tuyệt vời. Người ta cũng có thể ghi đè một thuộc tính bằng giải pháp này, phải không? cuối cùng ghi đè trước đó
besil

10

Có một số vấn đề về mặt cú pháp. Điều này đã làm việc cho tôi

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

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

Cảm ơn bạn @Yogesh, đây chính xác là những gì tôi đang tìm kiếm. Tôi muốn tận dụng các phong cách và có thể thêm nhiều hơn vào những thứ tôi cần.
TLee

4

Bạn sẽ muốn một cái gì đó như thế này:

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

    }
});

Trong ví dụ này, tôi lấy mảng các hàng, chứa dữ liệu cho các hàng trong thành phần và ánh xạ nó thành một mảng các thành phần Văn bản. Tôi sử dụng các kiểu nội tuyến để gọi getRandomColorhàm mỗi khi tôi tạo một thành phần Văn bản mới.

Vấn đề với mã của bạn là bạn xác định kiểu một lần và do đó getRandomColor chỉ được gọi một lần - khi bạn xác định kiểu.


Xin chào Colin, cảm ơn vì điều đó, nhưng làm cách nào tôi có thể chuyển các tham số kiểu khác cùng một lúc?
Pete Thorne,

Ý bạn là như style = {{backgroundColor: getRandomColor (), color: 'black'}}?
Colin Ramsay

Cảm ơn, điều đó sẽ hiệu quả nhưng tôi đã chấp nhận câu trả lời khác vì nó giúp chỉ ra cách bạn có thể chuyển một khối phong cách qua một lượt.
Pete Thorne,

2
Tôi thực sự nghĩ rằng câu trả lời khác là tốt hơn một quá :)
Colin Ramsay

2

Tôi biết điều này là cực kỳ muộn, nhưng đối với bất kỳ ai vẫn tự hỏi đây là một giải pháp dễ dàng.

Bạn chỉ có thể tạo một mảng cho các kiểu:

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

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

Màu thứ hai sẽ ghi đè bất kỳ màu nền gốc nào như đã nêu trong biểu định kiểu. Sau đó, có một chức năng thay đổi màu sắc:

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

Điều này sẽ tạo ra một màu hex ngẫu nhiên. Sau đó, chỉ cần gọi hàm đó bất cứ khi nào và bam, màu nền mới.


1

Tôi biết có một số câu trả lời, nhưng tôi nghĩ tốt nhất và đơn giản nhất là sử dụng trạng thái "Để thay đổi" là mục đích của trạng thái.

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

Bạn có thể liên kết giá trị trạng thái trực tiếp với đối tượng kiểu. Đây là một ví dụ:

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

Có, bạn có thể tạo phong cách năng động. Bạn có thể chuyển các giá trị từ các Thành phần.

Đầu tiên hãy tạo 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,
      }
    })
  }
}

sau đó sử dụng nó trong thành phần của bạn theo cách sau

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

Sử dụng toán tử lây lan đối tượng "..." phù hợp với tôi:

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

0

Ví dụ: nếu bạn đang sử dụng màn hình có bộ lọc và bạn muốn đặt nền của bộ lọc liên quan đến việc nó có được chọn hay không, bạn có thể thực hiện:

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

Bộ lọc đã đặt là:

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: hàm this.props.setVenueFilter(filters)là một hành động redux và this.props.venueFilterslà một trạng thái redux.


0

Trong trường hợp ai đó cần áp dụng điều kiện

 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

Đây là những gì đã làm việc cho tôi:

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

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

Vì một số lý do, đây là cách duy nhất để tôi cập nhật đúng cách.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.