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文件中标记的部分为修改后的代码,截图如下:


动画效果视频地址:https://pan.baidu.com/s/1AyooWPWXQGj2ZHCuuxWf3g

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页