原理在屏幕外部渲染一个fixHeader,通过监听scrollview的滚动offset,控制是否显示fixHeader
全部代码如下
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View,ScrollView,Image,TouchableWithoutFeedback,TextInput,Animated} from 'react-native';
import screen from '../util/Screen'
import appColor from '../util/appColor'
import Swiper from 'react-native-swiper'
import {ImageButton, BaseHeader} from '../widget'
import HouseRateView from '../components/Detail/HouseRateView'
import {Card} from 'react-native-shadow-cards'
import testJson from '../assets/detail'
const Pixel_644 = screen.scaleSize(644)
const Pixel_108 = screen.scaleSize(108)
const navHeight = screen.statusBarHeight + screen.headerHeight
const similerHouse = [
{
id:2553, circ:'一拍', start_time:'2018年09月20日', title:'深圳市宝安区观澜镇高尔夫大道观澜豪园*假日*赛维纳E栋L座0701',
similer_id:575627984615, currentPrice:1208600, consultPrice:1637000, discount:73.8,
area:65, price:'18,594', house_id:108779049
},
{
id:2553, circ:'一拍', start_time:'2018年09月20日', title:'深圳市宝安区观澜镇高尔夫大道观澜豪园*假日*赛维纳E栋L座0701',
similer_id:575627984615, currentPrice:1208600, consultPrice:1637000, discount:73.8,
area:65, price:'18,594', house_id:108779049
},
{
id:2553, circ:'一拍', start_time:'2018年09月20日', title:'深圳市宝安区观澜镇高尔夫大道观澜豪园*假日*赛维纳E栋L座0701',
similer_id:575627984615, currentPrice:1208600, consultPrice:1637000, discount:73.8,
area:65, price:'18,594', house_id:108779049
},
]
const menuItems = [
{
image:require('../image/basic_info.png'),
title:'基本信息'
},
{
image:require('../image/court_announce.png'),
title:'法院公告'
},
{
image:require('../image/house_value.png'),
title:'房产价值'
},
{
image:require('../image/school.png'),
title:'学校'
},
]
export default class Detail extends Component<Props> {
static navigationOptions = ({navigation}) =>({
header:null
})
constructor(props){
super(props);
this._onScroll = this._onScroll.bind(this)
this._onStop = this._onStop.bind(this)
this.renderFixHeader = this.renderFixHeader.bind(this)
this.fixHeaderY = 500
}
state = {
swiperItems: [require('../image/01.jpg'),require('../image/02.jpg'),require('../image/banner1.jpg')],
page: 1,
data:[1,2,3,4,5],
navOpacity:0,
scrollY:new Animated.Value(0),
currentPage:0
}
renderHeaderView(){
return (
<View style={{height:Pixel_644 ,width:screen.width}}>
<Swiper
style={{position:'absolute',left:0,top:0, width: screen.width}}
height={Pixel_644}
showsButtons={false}
removeClippedSubviews={false} //这个很主要啊,解决白屏问题
autoplay={true}
horizontal={true}
antoplayTimeout={2}
autoplayDirection={true}
dotStyle={styles.dotStyle}
activeDotStyle={styles.activeDotStyle}
paginationStyle={styles.paginationStyle}
>
{
this.state.swiperItems.map((item, index) => {
return (<Image style={{ height:Pixel_644, width: screen.width }}
key={index}
resizeMode='cover'
source={item} />)
})
}
</Swiper>
</View>
)
}
renderHouseCard(){
return(
<Card
style={{padding:screen.PIXEL_20,marginTop:-10, marginLeft:screen.PIXEL_10,marginBottom:screen.PIXEL_20,
marginRight:screen.PIXEL_10,width:screen.width - screen.PIXEL_20}}
>
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text style={{flex:1,fontSize:25,color:'#000'}} numberOfLines={2}>{testJson.title}</Text>
<View style={{marginLeft:screen.PIXEL_70}}>
<View style={{flexDirection:'row',alignItems:'center'}}>
<Image source={require('../image/alert.png')} style={{width:screen.PIXEL_30,height:screen.PIXEL_30}}/>
<Text>提醒</Text>
</View>
<View style={{flexDirection:'row', marginTop:screen.PIXEL_10,alignItems:'center'}}>
<Image source={require('../image/share.png')} style={{width:screen.PIXEL_30,height:screen.PIXEL_30}}/>
<Text>分享</Text>
</View>
</View>
</View>
<View style={{marginTop:screen.PIXEL_10}}>
<Text style={{color:appColor.textColor3,fontSize:18}}>{testJson.start_time}
<Text style={{color:'#000',fontSize:23}}> 至 </Text>
<Text> {testJson.end_time} </Text>
</Text>
<Text style={{color:appColor.textColor4}}>{testJson.applyCount}人报名 {testJson.noticeCnt}人设置提醒 {testJson.viewerCount}次围观</Text>
<View style={{height:1,marginTop:screen.PIXEL_10,marginLeft:0, marginRight:0,backgroundColor:appColor.textColor4}}/>
</View>
<View style={{flexDirection:'row',marginTop:screen.PIXEL_10}}>
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>起拍价</Text>
<Text style={{fontSize:18,color:'#e98d75',fontWeight:'bold'}}>1143万</Text>
</View>
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>法院评估价</Text>
<Text style={{fontSize:18,color:'#e98d75',fontWeight:'bold'}}>1143万</Text>
</View>
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>市场评估价</Text>
<Text style={{fontSize:18,color:'#e98d75',fontWeight:'bold'}}>1143万</Text>
</View>
</View>
<View style={{marginTop:screen.PIXEL_20,flexDirection:'row',justifyContent:'space-around'}}>
<View style={{width:screen.scaleSize(196),height:screen.scaleSize(45),backgroundColor:'#e8f3f7',
justifyContent:'center',alignItems:'center',borderRadius:screen.PIXEL_10
}}>
<Text style={{fontSize:10,color:appColor.textBlueColor}}>8折</Text>
</View>
<View style={{width:screen.scaleSize(196),height:screen.scaleSize(45),backgroundColor:'#e8f3f7',
justifyContent:'center',alignItems:'center',borderRadius:screen.PIXEL_10
}}>
<Text style={{fontSize:10,color:'#a1ccd7'}}>一拍</Text>
</View>
<View style={{width:screen.scaleSize(196),height:screen.scaleSize(45),backgroundColor:'#e3f3eb',
justifyContent:'center',alignItems:'center',borderRadius:screen.PIXEL_10
}}>
<Text style={{fontSize:10,color:'#76b999'}}>住宅</Text>
</View>
</View>
</Card>
)
}
renderMenuItem(item,index){
let isSelect = this.state.currentPage == index
return (
<TouchableWithoutFeedback
key={index}
onPress={()=>{
if(index > 0){
//法院公告
this.props.navigation.navigate('DetailSecond',{index:index-1})
}
// this.setState({
// currentPage:index
// })
}}
>
<View style={{flex:1,justifyContent:'center',alignItems:'center',
borderBottomColor:'#fff',borderBottomWidth:isSelect ? 3 : 0,
}}>
<Image source={item.image} style={{width:screen.PIXEL_40,height:screen.PIXEL_40}}/>
<Text style={{fontSize:16,color:'#fff',marginTop:screen.PIXEL_10}}>{item.title}</Text>
</View>
</TouchableWithoutFeedback>
)
}
renderSelectView(){
let itemViews = []
menuItems.map((item,index)=>{
let itemView = this.renderMenuItem(item,index)
itemViews.push(itemView)
})
return(
<View style={ {width:screen.width,height:screen.PIXEL_120,backgroundColor:'#2198f2',flexDirection:'row'} }
onLayout={(e)=>{
console.log(e.nativeEvent)
this.fixHeaderY = e.nativeEvent.layout.y
}}
>
{itemViews}
</View>
)
}
renderInfoView(){
return(
<View style={{width:screen.width,paddingLeft:screen.PIXEL_20,paddingRight:screen.PIXEL_20}}>
<View style={{flexDirection:'row',marginTop:screen.PIXEL_10}}>
<View style={{flex:1}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>保证金:
<Text style={{color:appColor.textColor2}}> {(testJson.forecast_safe/10000).toFixed(0)}万</Text>
</Text>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>单价:
<Text style={{color:appColor.textColor2}}> {testJson.average.toFixed(0)}/㎡</Text>
</Text>
</View>
</View>
<View style={{flexDirection:'row',marginTop:screen.PIXEL_10}}>
<View style={{flex:1}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>楼层:
<Text style={{color:appColor.textColor2}}> {testJson.floor}</Text>
</Text>
</View>
<View style={{flex:1}}>
<Text style={{fontSize:18,color:appColor.textColor4}}>年代:
<Text style={{color:appColor.textColor2}}> {testJson.build_time}</Text>
</Text>
</View>
</View>
<Text style={{fontSize:18,color:appColor.textColor4,marginTop:screen.PIXEL_10}}>面积:
<Text style={{color:appColor.textColor2}}> {testJson.area}㎡</Text>
</Text>
<Text style={{fontSize:18,color:appColor.textColor4,marginTop:screen.PIXEL_10}}>税费:
<Text style={{color:appColor.textColor2}}> {testJson.tax}</Text>
</Text>
<Text style={{fontSize:18,color:appColor.textColor4,marginTop:screen.PIXEL_10}}>小区:
<Text style={{color:appColor.textColor2}}> {testJson.community_name}</Text>
</Text>
<Text style={{fontSize:18,color:appColor.textColor4,marginTop:screen.PIXEL_10}}>学校:
<Text style={{color:appColor.textColor2}}> {testJson.area}㎡</Text>
</Text>
<Text style={{fontSize:18,color:appColor.textColor4,marginTop:screen.PIXEL_10}}>轨交:
<Text style={{color:appColor.textColor2}}> {testJson.area}㎡</Text>
</Text>
<View style={{flexDirection:'row',width:screen.width,marginTop:screen.PIXEL_10}}>
<Text style={{fontSize:18,color:appColor.textColor4,width:screen.PIXEL_90}}>位置:</Text>
<Text style={{fontSize:18,color:appColor.textColor2,width:screen.width-screen.PIXEL_120}} numberOfLines={2}> {testJson.location}</Text>
</View>
<View style={{flex:1,height:0.3,backgroundColor:appColor.textColor4,marginTop:screen.PIXEL_10,}}/>
</View>
)
}
//同区历史成交
renderSimilerHouse(){
let cells = [];
similerHouse.map((item,index)=>{
let subtitle = `${item.discount}折 单价${item.price}/㎡ 面积${item.area}㎡`;
let cell = (
<View style={{flex:1,height:screen.PIXEL_230,flexDirection:'row'}}
key={index}
>
<View style={{alignItems:'center'}}>
<View style={{width:screen.PIXEL_30,height:screen.PIXEL_30,borderRadius:screen.PIXEL_30/2,backgroundColor:appColor.navBgColor,overflow:'hidden'}}/>
<View style={{width:screen.PIXEL_10/2,flex:1,backgroundColor:appColor.navBgColor}}/>
</View>
<View style={{flex:1,marginLeft:screen.PIXEL_40,marginRight:screen.PIXEL_20}}>
<Text style={{fontSize:18,color:appColor.textColor2,marginTop:screen.PIXEL_10}} numberOfLines={3}>{item.title}</Text>
<Text style={{fontSize:17,color:appColor.textColor4,marginTop:screen.PIXEL_20}} numberOfLines={1}>{subtitle}</Text>
</View>
<Text style={{fontSize:18,color:'#d6949b',alignSelf:'center'}}>{(item.currentPrice/10000).toFixed(0)}万</Text>
</View>
)
cells.push(cell)
})
return(
<View style={{width:screen.width,padding:screen.PIXEL_20}}>
<View style={{flex:1, flexDirection:'row',marginBottom:screen.PIXEL_10}}>
<Text style={{fontSize:18,color:appColor.textColor2,flex:1}}>同区历史成交</Text>
<TouchableWithoutFeedback
onPress={()=>{
this.props.navigation.navigate('DetailSecond',{index:1})
}}
>
<View style={{flexDirection:'row', alignItems:'center'}}>
<Text style={{fontSize:18,color:appColor.textBlueColor}}>更多</Text>
<Image source={require('../image/right.png')} style={{width:screen.PIXEL_30,height:screen.PIXEL_30,tintColor:appColor.textBlueColor}}/>
</View>
</TouchableWithoutFeedback>
</View>
{cells}
</View>
)
}
renderBottomView(){
return(
<View style={{height:screen.PIXEL_120,flexDirection:'row',alignItems:'center',backgroundColor:'#fff'}}>
<TouchableWithoutFeedback>
<View style={{width:screen.PIXEL_230,alignItems:'center'}}>
<Image source={require('../image/collect1.png')} style={{width:screen.PIXEL_50,height:screen.PIXEL_50}}/>
<Text style={{fontSize:17,color:appColor.textColor4}}>加入收藏</Text>
</View>
</TouchableWithoutFeedback>
<View style={{flex:1,flexDirection:'row',height:screen.PIXEL_100}}>
<TouchableWithoutFeedback>
<View style={{flex:1,justifyContent:'center',alignItems:'center',backgroundColor:'#ffae7a'}}>
<Text style={{color:'#fff',fontSize:20}}>一键贷款</Text>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback>
<View style={{flex:1,justifyContent:'center',alignItems:'center',backgroundColor:appColor.navBgColor}}>
<Text style={{color:'#fff',fontSize:20}}>马上咨询</Text>
</View>
</TouchableWithoutFeedback>
</View>
</View>
)
}
renderFixHeader() {
let showY = this.state.scrollY.interpolate({
inputRange: [0, this.fixHeaderY, this.fixHeaderY, this.fixHeaderY],
outputRange: [-9999, -9999, 0, 0]
})
console.log(showY)
let itemViews = []
menuItems.map((item,index)=>{
let itemView = this.renderMenuItem(item,index)
itemViews.push(itemView)
})
return(
<Animated.View style={ {
position: 'absolute', top: navHeight, left: 0,
width:screen.width,height:screen.PIXEL_120,backgroundColor:'#2198f2',flexDirection:'row',
transform: [
{translateY: showY}
]
}}
>
{itemViews}
</Animated.View>
)
}
render() {
let leftItem = (
<TouchableWithoutFeedback
onPress={()=>{
this.props.navigation.goBack()
}}
>
<View >
<View style={{width:screen.PIXEL_80, height:screen.PIXEL_80,
borderRadius:screen.PIXEL_40,backgroundColor:'#000',opacity:this.state.navOpacity < 0.5 ? 0.5 : 0}}/>
<View style={{position:'absolute',justifyContent:'center',alignItems:'center',top:0,left:0,bottom:0,right:0}}>
<Image source={require('../image/back_white.png')}
resizeMode={'contain'}
style={{width:screen.PIXEL_50,height:screen.PIXEL_50}}/>
</View>
</View>
</TouchableWithoutFeedback>
)
let rightItem = (
<TouchableWithoutFeedback
onPress={()=>{
this.props.navigation.goBack()
}}
>
<View >
<View style={{width:screen.PIXEL_80, height:screen.PIXEL_80,
borderRadius:screen.PIXEL_40,backgroundColor:'#000',opacity:this.state.navOpacity < 1 ? 0.5 : 0}}/>
<View style={{position:'absolute',justifyContent:'center',alignItems:'center',top:0,left:0,bottom:0,right:0}}>
<Image source={require('../image/collect.png')}
resizeMode={'contain'}
style={{width:screen.PIXEL_50,height:screen.PIXEL_50}}/>
</View>
</View>
</TouchableWithoutFeedback>
)
return (
<View style={styles.container}>
<BaseHeader
ref={ref=>this.navBar = ref}
title={'详情'}
opacity={this.state.navOpacity}
leftItem={leftItem}
rightItem={rightItem}
/>
<ScrollView
ref={ref=>{ this._scrollView = ref }}
style={{marginTop:-navHeight}}
// onScroll={this._onScroll}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}],
{listener:this._onScroll}
)}
onScrollEndDrag={this._onStop}
scrollEventThrottle={16}
>
{this.renderHeaderView()}
{this.renderHouseCard()}
{this.renderSelectView()}
{this.renderInfoView()}
{this.renderSimilerHouse()}
<HouseRateView />
</ScrollView>
{this.renderBottomView()}
{this.renderFixHeader()}
</View>
);
}
_onScroll(event){
let y = event.nativeEvent.contentOffset.y + navHeight;
console.log(y)
if (y < Pixel_644) {
this.setState({
navOpacity:0
})
} else {
this.setState({
navOpacity:1
})
}
}
_onStop(e){
let {x,y}= e.nativeEvent.contentOffset
// console.log(y)
// let fixY = this.fixHeaderY - screen.statusBarHeight - screen.headerHeight;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
paginationStyle: {
bottom: 20,
},
dotStyle: {
width: 8,
height: 8,
backgroundColor: '#fff',
opacity: 0.4,
borderRadius: 4,
},
activeDotStyle: {
width: 8,
height: 8,
backgroundColor: '#00ad63',
borderRadius: 4,
},
});
网友评论