How to animate the list items when list is loaded in react native
京东淘宝风格的商品视图
手机屏幕左右边缘紧靠图片左右边缘图片之间留间隙,这种style的渲染技巧互联网上你可能很难搜到
列表项动画基于以下基础代码实现:
src/ListItem.js文件完整的代码如下:
import React,{Component} from 'React';
import {
TouchableWithoutFeedback,
Image,
Animated,
} from 'react-native';
export default class ListItem extends Component {
state = {
animatePress: new Animated.Value(1),
}
animateIn() {
Animated.timing(this.state.animatePress, {
toValue: 0.8,
duration: 200
}).start()
}
animateOut() {
Animated.timing(this.state.animatePress, {
toValue: 1,
duration: 200
}).start()
}
render() {
const { itemWidth, image, onPressItem } = this.props
return (
<TouchableWithoutFeedback
onPress = {() => onPressItem && onPressItem(this.props.image)}
onPressIn = {() => this.animateIn()}
onPressOut = {() => this.animateOut()}
>
<Animated.View style = {{
marginTop: 2,
marginBottom: 2,
paddingRight: 4,
transform: [
{
scale: this.state.animatePress
},
]
}}>
<Image style={{ width: itemWidth, height: 200 }} source={image} />
</Animated.View>
</TouchableWithoutFeedback>
);
}
}
App.js文件完整的代码如下:import React,{Component} from 'React';
import {
StyleSheet,
FlatList,
View,
Button,
Dimensions
} from 'react-native';
import ListItem from './src/ListItem';
const ITEM_WIDTH = Dimensions.get('window').width;
export default class App extends Component {
state = {
columns: 1,
key: 1,
array: [],
}
constructor(props) {
super(props)
this.getImageData = this.getImageData.bind(this)
}
componentWillMount() {
this.getImageData()
}
getImageData() {
fetch('https://randomuser.me/api?page=1&results=10&inc=picture,name',{
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then((response) => response.json())
.then((responseJson) => {
let newArray = this.state.array.slice()
let concatArray = newArray.concat(responseJson.results)
this.setState({
array: concatArray
})
})
}
render() {
const { columns, key, array } = this.state
return (
<View style={{flex:1}}>
<Button
onPress = {() => {
let { columns, key } = this.state
columns = columns === 3 ? 1 : 3
this.setState({ columns: columns, key: key + 1 })
}}
title = 'Toggle Layout'
/>
<View style = {styles.container}>
<FlatList
key = {key}
numColumns = {columns}
data = {array}
renderItem = {({ item, index }) => {
return <ListItem
itemWidth = {ITEM_WIDTH / columns - 2 }
image = {{ uri: item.picture.large }} />
}}
keyExtractor = {
(item, index) => { return `${item.name.first + index}` }
}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5fcff',
justifyContent: 'space-around',
flexDirection:'row',
}
})
支持苹果手机的https协议链接请求,我们需要配置info.plist文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>jason</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>
本范例使用的链
https://randomuser.me/api?page=1&results=10&inc=picture,name
接返回的数据如下:{
"results": [{
"name": {
"title": "mr",
"first": "eric",
"last": "price"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/40.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/40.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/40.jpg"
}
}, {
"name": {
"title": "ms",
"first": "sheryl",
"last": "long"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/57.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/57.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/57.jpg"
}
}, {
"name": {
"title": "mr",
"first": "everett",
"last": "perry"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/49.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/49.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/49.jpg"
}
}, {
"name": {
"title": "miss",
"first": "nella",
"last": "palo"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/49.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/49.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/49.jpg"
}
}, {
"name": {
"title": "mr",
"first": "maxime",
"last": "jones"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/79.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/79.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/79.jpg"
}
}, {
"name": {
"title": "miss",
"first": "audrey",
"last": "webb"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/24.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/24.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/24.jpg"
}
}, {
"name": {
"title": "monsieur",
"first": "soren",
"last": "lambert"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/98.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/98.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/98.jpg"
}
}, {
"name": {
"title": "miss",
"first": "clara",
"last": "nieto"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/31.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/31.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/31.jpg"
}
}, {
"name": {
"title": "miss",
"first": "kübra",
"last": "düşenkalkar"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/80.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/80.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/80.jpg"
}
}, {
"name": {
"title": "mrs",
"first": "michelle",
"last": "garza"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/39.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/39.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/39.jpg"
}
}],
"info": {
"seed": "9639f987ad3e2210",
"results": 10,
"page": 1,
"version": "1.1"
}
}
在安卓和苹果手机模拟器中运行的效果截图如下:
真正实现列表图片动画效果的步骤就从这儿开始吧
动画效果一
我们需要在以上项目中只需要修改ListItem.js代码文件,下图中标记的部分为新增加的代码行,截图如下:
动画效果视频地址:https://pan.baidu.com/s/1I1bSxqkDsDYCIgFw8mqv5Q
动画效果二
注意App.js文件中标记的部分为新增加的代码行,截图如下:
注意ListItem.js文件中标记的部分为新增加的代码行,截图如下:
动画效果视频地址:https://pan.baidu.com/s/1-uuuf0S_3i67WgGaDWWmzg
动画效果三
只需要修改ListItem.js代码文件,下图中标记的部分为修改后的代码块,截图如下:
动画效果视频地址:https://pan.baidu.com/s/1bdCL_oYq0xjHdwpHrG7Rpg
动画效果四
只需要修改ListItem.js代码文件,下图中标记的部分为修改后的代码块,截图如下:
动画效果视频地址:https://pan.baidu.com/s/1JZNHKm7OcNpP2rt9cIUX8A
动画效果五
注意App.js文件中标记的部分为新增加的代码,截图如下:
注意ListItem.js文件中标记的部分为修改后的代码,截图如下:
动画效果视频地址:https://pan.baidu.com/s/1toHEv5qM2OdDtckmb8zu9Q
动画效果六
注意App.js文件中标记的部分为新增加的代码,截图如下
注意ListItem.js文件中标记的部分为修改后的代码,截图如下: