界面开发
Styles
在讲解
你并没有被允许去为整个节点树设置一个默认的譬如字体这样的属性,推荐的方式是通过创建一个带有一致的字体样式的组件并且在整个应用中通过重用组件的方式来完成样式的统一与继承。
在
Declaring & Manipulating Styles
类似于
Inline Styles( 内联样式)
内联样式是句法上最简单的使用方法,不过很明显并不是最佳的使用方法,其语法形式类似于
<Text>
The quick <Text style={{fontStyle: "italic"}}>brown</Text> fox
jumped over the lazy <Text style={{fontWeight: "bold"}}>dog</Text>.
</Text>
内联样式可以让你快速地实验,不过,这种方式还是要尽可能地避免,毕竟这种方式会非常的低效。内联样式对象可能在每次渲染的时候被重新创建。即使你有可能在
Styling With Objects
对于内联样式最简单的修正就是将这些样式对象提取出来,作为单独的
var italic = {
fontStyle: 'italic'
};
var bold = {
fontWeight: 'bold'
};
...
render() {
return (
<Text>
The quick <Text style={italic}>brown</Text> fox
jumped over the lazy <Text style={bold}>dog</Text>.
</Text>
);
}
不过,StyleSheet.create
来创建一个样式对象,而不是仅仅使用简单的StyleSheet.create
是可选的一种方式但是能够提供很多的好处,它通过将样式对象转化为一个内部表的引用来保证了值是不可变对象并且是不透明的。将它放置到文件末尾,可以保证在整个应用的生命周期中只会创建一次而不是每次渲染的时候都会重新创建。由此可见,StyleSheet.create
是一点语法糖,同时,也方便了你进行StyleSheet.create
创建的样式对象可以用
Style Concatenation
虽然
var styles = Stylesheet.create({
button: {
borderRadius: '8px',
backgroundColor: '#99CCFF'
},
accentText: {
fontSize: '18px',
fontWeight: 'bold'
}
});
然后希望创建一个对象同时用这两个属性:
var AccentButton = React.createClass({
render: function() {
return (
<Text style={[styles.button, styles.accentText]}>
{this.props.children}
</Text>
);
}
});
可以看出,这个
var AccentButton = React.createClass({
render: function() {
return (
<Text style={[styles.button, styles.accentText, {color: '#FFFFFF'}]}>
{this.props.children}
</Text>
);
}
});
如果存在冲突的话,就是为一个属性定义了两个值的时候,<Button />
组件,希望能在被触摸时展示额外的样式,则可以使用:
<View style={[styles.button, this.state.touching && styles.highlight]} />
Organization and Inheritance
在一个大型的项目中会存在着大量的组件以及各种各样的样式定义,而这时候我们就需要来考虑怎么组织编排这些样式文件。
Exporting Style Objects
随着样式定义的日渐复杂,我们会希望样式文件独立于主的<ComponentName />
,可以创建一个叫
- ComponentName
|- index.js
|- styles.js
而在
'use strict';
var React = require('react-native');
var {
StyleSheet,
} = React;
var styles = Stylesheet.create({
text: {
color: '#FF00FF',
fontSize: 16
},
bold: {
fontWeight: 'bold'
}
});
module.exports = styles;
在
var styles = require('./styles.css');
接下来就可以在我们的组件中使用了:
'use strict';
var React = require('react-native');
var styles = require('./styles.css');
var {
View,
Text,
StyleSheet
} = React;
var ComponentName = React.createClass({
render: function() {
return (
<Text style={[styles.text, styles.bold]}>
Hello, world
</Text>
);
}
});
Passing Styles as Props
You can also pass styles as properties. The propType View.propTypes.style
ensures that only valid styles are passed as props.
You can use this pattern to create extensible components, which can be more effectively controlled and styled by their parents. For example, a component might take in an optional style prop:
'use strict';
var React = require('react-native');
var {
View,
Text
} = React;
var CustomizableText = React.createClass({
propTypes: {
style: Text.propTypes.Style
},
getDefaultProps: function() {
return {
style: {}
};
},
render: function() {
return (
<Text style={[myStyles.text, this.props.style]}>Hello, world</Text>
);
}
});
Reusing and Sharing Styles
We typically prefer to reuse styled components, rather than reusing styles, but there are clearly some instances in which you will want to share styles between components. In this case, a common pattern is to organize your project roughly like so:
- js
|- components
|- Button
|- index.js
|- styles.js
|- styles
|- styles.js
|- colors.js
|- fonts.js
By having separate directories for components and for styles, you can keep the intended use of each file clear based on context. A component’s folder should contain its React class, as well as any component-specific files. Shared styles should be kept out of component folders. Shared styles may include things such as your palette, fonts, standardized margin and padding, and so on.
styles/styles.js
requires the other shared styles files, and exposes them; then your components can require styles.js
and use shared files as needed. Or, you may prefer to have components require specific stylesheets from the styles/
directory instead.
Because we’ve now moved our styles into Javascript, organizing your styles is really a question of general code organization; there’s no single correct approach here.
Css Polyfill
很多时候我们
Utils( 辅助类)
Media Query
在
var Dimensions = require('Dimensions');
var { width, height } = Dimensions.get('window');
Background
BackgroundImage
背景图片是在


var styles = StyleSheet.create({
bgImageWrapper: {
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
},
bgImage: {
flex: 1,
resizeMode: "stretch",
},
welcome: {
fontSize: 20,
textAlign: "center",
margin: 10,
},
});
<View style={{ flex: 1 }}>
<View style={styles.bgImageWrapper}>
<Image source={require("image!background")} style={styles.bgImage} />
</View>
<Text style={styles.welcome}>Welcome to React Native!</Text>
</View>;
SASS
Animation
Graphic
Shapes
Layout & Position
One of the biggest changes when working with styling in React Native is positioning. CSS supports a proliferation of positioning techniques. Between float
, absolute positioning, tables, block layout, and more, it’s easy to get lost! React Native’s approach to positioning is more focused, relying primarily on flexbox
as well as absolute positioning, along with the familiar properties of margin
and padding
. In this section, we’ll look at how layouts are constructed in React Native, and finish off by building a layout in the style of a Mondrian painting.
Flexbox
Flexbox is a CSS3 layout mode. Unlike existing layout modes such as block
and inline
, flexbox gives us a direction-agnostic way of constructing layouts. (That’s right: finally, vertically centering is easy!) React Native leans heavily on flexbox. If you want ot read more about the general specification, the MDN documentation is a good place to start.
With React Native, the following props are related to flexbox:
- flex
- flexDirection
- flexWrap
- alignSelf
- alignItems
Additionally, these related values impact layout:
- height
- width
- margin
- border
- padding
If you have worked with flexbox on the web before, there won’t be many surprises here. Because flexbox is so important to constructing layouts in React Native, though, we’ll spend some time now exploring how it works.
The basic idea behind flexbox is that you should be able to create predictably structured layouts even given dynamically sized elements. Since we’re designing for mobile, and need to accommodate multiple screen sizes and orientations, this is a useful feature.
We’ll start with a parent ``, and some children.
<View style={styles.parent}>
<Text style={styles.child}> Child One </Text>
<Text style={styles.child}> Child Two </Text>
<Text style={styles.child}> Child Three </Text>
</View>
To start, we’ve applied some basic styles to the views, but haven’t touched the positioning yet.
var styles = StyleSheet.create({
parent: {
backgroundColor: '#F5FCFF',
borderColor: '#0099AA',
borderWidth: 5,
marginTop: 30
},
child: {
borderColor: '#AA0099',
borderWidth: 2,
textAlign: 'center',
fontSize: 24,
}
});
Next, we will set flex on both the parent and the child. By setting the flex property, we are explicitly opting-in to flexbox behavior. flex takes a number. This number determines the relative weight each child gets; by setting it to 1 for each child, we weight them equally. We also set flexDirection: column so that the children are laid out vertically. If we switch this to flexDirection: row, the children will be laid out horizontally instead.
var styles = StyleSheet.create({
parent: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#F5FCFF',
borderColor: '#0099AA',
borderWidth: 5,
marginTop: 30
},
child: {
flex: 1,
borderColor: '#AA0099',
borderWidth: 2,
textAlign: 'center',
fontSize: 24,
}
});
If we set alignItems, the children will no longer expand to fill all available space in both directions. Because we have set flexDirection: row, they will expand to fill the row. However, now they will only take up as much vertical space as they need. Then, the alignItems value determines where they are positioned along the cross-axis. The cross-axis is the axis orthogonal to the flexDirection. In this case, the cross axis is vertical. flex-start places the children at the top, center centers them, and flex-end places them at the bottom. Let’s see what happens when we set alignItems:
var styles = StyleSheet.create({
parent: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start',
backgroundColor: '#F5FCFF',
borderColor: '#0099AA',
borderWidth: 5,
marginTop: 30
},
child: {
flex: 1,
borderColor: '#AA0099',
borderWidth: 2,
textAlign: 'center',
fontSize: 24,
}
});
Absolute Position
In addition to flexbox, React Native supports absolute positioning. It works much as it does on the web. You can enable it by setting the position property: position: absolute Then, you can control the component’s positioning with the familiar properties of left, right, top, and bottom. An absolutely positioned child will apply these coordinates relative to its parent’s position, so you can lay out a parent element using flexbox and then use absolute position for a child within it. There are some limitations to this. We don’t have z-index, for instance, so layering views on top of each other is a bit complicated. The last view in a stack typically takes precedence. Absolute positioning can be very useful. For instance, if you want to create a container view that sits below the iOS status bar, absolute positioning makes this easy:
container: {
position: 'absolute',
top: 30,
left: 0,
right: 0,
bottom: 0
}
Mixed Example
Let’s try using these positioning techniques to create a more complicated layout. Say we want to mimic a Mondrian painting. Here’s the end result:
To start with, we create a parent style to act as the container. We will use absolute positioning on the parent, because it’s most appropriate: we want it to fill all available space, except with a 30 pixel offset at the top, due to the iOS status bar. We’ll also set its flexDirection to column.
parent: {
flexDirection: 'column',
position: 'absolute',
top: 30,
left: 0,
right: 0,
bottom: 0
}
Looking back at the image, we can divide the layout up into larger blocks. These divisions are in many ways arbitrary, so we’ll pick an option and roll with it. Here’s one way we can segment the layout: We start by cutting the layout into a top and bottom block:
<View style={styles.parent}>
<View style={styles.topBlock}>
</View>
<View style={styles.bottomBlock}>
</View>
</View>
Then we add in the next layer. This includes both a “left column” and “bottom right” sector, as well as the actual
<View style={styles.parent}>
<View style={styles.topBlock}>
<View style={styles.leftCol}>
</View>
<View style={[styles.cellThree, styles.base]} />
</View>
<View style={styles.bottomBlock}>
<View style={[styles.cellFour, styles.base]}/>
<View style={[styles.cellFive, styles.base]}/>
<View style={styles.bottomRight}>
</View>
</View>
</View>
The final markup contains all seven cells:
<View style={styles.parent}>
<View style={styles.topBlock}>
<View style={styles.leftCol}>
<View style={[styles.cellOne, styles.base]} />
<View style={[styles.base, styles.cellTwo]} />
</View>
<View style={[styles.cellThree, styles.base]} />
</View>
<View style={styles.bottomBlock}>
<View style={[styles.cellFour, styles.base]}/>
<View style={[styles.cellFive, styles.base]}/>
<View style={styles.bottomRight}>
<View style={[styles.cellSix, styles.base]} />
<View style={[styles.cellSeven, styles.base]} />
</View>
</View>
</View>
Now let’s add the styles that make it work. (Show stylesheet.)··
// Mondrian/style.js
'use strict';
var React = require('react-native');
var {
StyleSheet,
} = React;
var styles = StyleSheet.create({
parent: {
flexDirection: 'column',
position: 'absolute',
top: 30,
left: 0,
right: 0,
bottom: 0
},
base: {
borderColor: '#000000',
borderWidth: 5
},
topBlock: {
flexDirection: 'row',
flex: 5
},
leftCol: {
flex: 2
},
bottomBlock: {
flex: 2,
flexDirection: 'row'
},
bottomRight: {
flexDirection: 'column',
flex: 2
},
cellOne: {
flex: 1,
borderBottomWidth: 15
},
cellTwo: {
flex: 3
},
cellThree: {
backgroundColor: '#FF0000',
flex: 5
},
cellFour: {
flex: 3,
backgroundColor: '#0000FF'
},
cellFive: {
flex: 6
},
cellSix: {
flex: 1
},
cellSeven: {
flex: 1,
backgroundColor: '#FFFF00'
}
});
module.exports = styles;