How to animate the list items when list is loaded in react native

原创 2018年04月16日 15:05:12

京东淘宝风格的商品视图

手机屏幕左右边缘紧靠图片左右边缘图片之间留间隙,这种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

React Native之学习ListView的单选以及记录数据

我们对于ReactNative重新更新界面是重新渲染,然后如果是列表过长的情况下,我们一般来说会使用ListView来提高性能,以及提高局部渲染的问题。所以在我们在服务器那边获取下来的数据例如:[{n...
  • fox_wei_hlz
  • fox_wei_hlz
  • 2017-04-24 09:58:50
  • 1272

react native 控件联动

需求: //控件联动 //在修改下面的input内容后,上面的textview改变内容 步骤 //1 创建上面的textview//2 创建下面的input//3.监听input的内容改...
  • hehe0705
  • hehe0705
  • 2017-03-24 00:11:10
  • 251

React Native填坑之旅--动画篇

动画是提高用户体验不可缺少的一个元素。恰如其分的动画可以让用户更明确的感知当前的操作是什么。无疑在使用React Native开发应用的时候也需要动画。这就需要知道RN都给我们提供了那些动画,和每个动...
  • future_challenger
  • future_challenger
  • 2016-09-27 20:41:46
  • 3005

React技巧3(如何优雅的渲染一个List)

本教程总共5篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章! 1.React 技巧1(状态组件与无状态组件的使用) ----2018.01.04...
  • oKeYue
  • oKeYue
  • 2018-01-06 19:32:33
  • 131

react_native 项目实战 (6) 趋势页面 列表抽取 popover使用

父控件 更新子控件 通过属性传值现在写趋势页面. 其实趋势页面和最热页面都差不多. 趋势页面的导航条是有个popover的控件 所以不是简单的text 需要改造NavigationBar需要改造Na...
  • liudao7994
  • liudao7994
  • 2017-10-30 11:56:18
  • 167

React Native JavaScriptModuleRegistry是如何存放入JS接口原型的

mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() ...
  • rnZuoZuo
  • rnZuoZuo
  • 2016-11-19 18:48:13
  • 568

React-Native滑动删除react-native-swipe-list-view

https://github.com/jemise111/react-native-swipe-list-view react-native-swipe-list-view  is a...
  • sinat_17775997
  • sinat_17775997
  • 2017-02-13 15:49:01
  • 2443

react native SectionList 使用详解

SectionList 和FlatList的基本一样,和FlatList一样的地方就不介绍啦。那什么时候使用FlatList,什么时候使用SectionList呢?如果你的列表不需要分组,那么可以使用...
  • mengks1987
  • mengks1987
  • 2017-04-19 09:29:07
  • 6391

React Native学习五- FlatList

高性能的简单列表组件,支持下面这些常用的功能: 完全跨平台。支持水平布局模式。行组件显示或隐藏时可配置回调事件。支持单独的头部组件。支持单独的尾部组件。支持自定义行间分隔线。支持下拉刷新。支持上...
  • wgl_happy
  • wgl_happy
  • 2017-05-03 15:38:55
  • 8244

React Native ListView 长按删除

项目中React Native ListView的长按删除功能分享: /** * Sample React Native App * https://github.com/facebook/rea...
  • chichengjunma
  • chichengjunma
  • 2016-11-25 09:57:38
  • 1986
收藏助手
不良信息举报
您举报文章:How to animate the list items when list is loaded in react native
举报原因:
原因补充:

(最多只允许输入30个字)