注意:当前测试的react-native版本为 0.36.0,上次碰到版本忘记的好像是0.30.0这个动画无效果,高度收不起来,具体原因未知,但是较早的版本好像又有用的,所以刚好有些朋友碰到的版本无效的可能要换种思维去处理了,避免把你带入坑而死磕,特此注明。
大致思路挺简单的:
1、展开效果可以通过Animated动画来实现,思路大致为,给Animated高度为0,当单击时Animated展开一定高度,这样就完成了展开的效果
2、ListView是以单个显示元素来累积起来的,所以可以写一个组件,主要包含listView中显示部分和隐藏部分(即需要单击展开收起部分)。
测试代码如下:
自定义listView单个元素组件,包含可视部分和隐藏展开收起部分,自定义元素代码如下,文件名称为ListCards.js:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Animated
} from 'react-native';
class ListCards extends Component {
constructor(props) {
super(props);
this.state={
...props,
showAnim:new Animated.Value(0)
};
this.showorhide=0;
}
_showorhideItems(){
if(typeof(this.state.name)=='undefined'||this.state.name==null){
return;
}
Animated.timing( // Uses easing functions
this.state.showAnim, // The value to drive
{
toValue: this.showorhide==0?1:0
} // Configuration
).start();
this.showorhide=this.showorhide==0?1:0;
}
render(){
return(
<View>
<TouchableOpacity onPress={this._showorhideItems.bind(this)}>
<View style={styles.headerLine}>
<View style={styles.headerRows}><Text>{this.state.name}</Text></View>
</View>
</TouchableOpacity>
<Animated.View
style={{
height:this.state.showAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 110]
}),
overflow:'hidden'
}
}
>
<View style={styles.showitemContain}>
<View style={{height:50}}>
<Text>{this.state.title==null?'':this.state.title}</Text>
</View>
<View style={{height:60}}>
<Text>{this.state.fromwhere==null?'':this.state.fromwhere}</Text>
</View>
</View>
</Animated.View>
</View>
)
}
}
const styles=StyleSheet.create({
headerLine:{
height:50,
flexDirection:'row',
borderBottomWidth:1,
borderBottomColor:'red',
},
headerRows:{
flex:1,
justifyContent:'center',
alignItems:'center',
},
showitemContain:{
borderWidth:1,
borderColor:'red',
height:110,
justifyContent:'center',
alignItems:'center',
}
});
module.exports=ListCards;
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
ListView
} from 'react-native';
import ListCards from './listcards';
class ListContent extends Component{
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state={
dataSource: ds.cloneWithRows(this._genrows()),
};
}
// componentWillMount(){
// this.setState({dataSource:this.state.dataSource.cloneWithRows(this._genrows())});
// }
_genrows(){
var rows=[];
for(let i=0;i<5;i++){
var rowtmp={};
rowtmp.name='测试'+i;
rowtmp.title='标题'+i;
rowtmp.fromwhere='来源'+i;
rows.push(rowtmp);
}
console.log(JSON.stringify(rows));
return rows;
}
_renderRows(rowData){
return(
<ListCards name={rowData.name} title={rowData.title} fromwhere={rowData.fromwhere} />
)
}
render(){
return(
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) =>this._renderRows(rowData)}
/>
)
}
}
module.exports=ListContent;
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import ListContent from './component/listContent';
AppRegistry.registerComponent('testProject', () => ListContent);
效果为:单击某一行,则展开那一行的隐藏数据,太晚了,就懒得做gif图看效果了,直接复制粘贴,运行测试一下便可以看到效果了,根据这样的思路,便可以完成自己想要的展开的内容了,good luck。