美文网首页
react-native ScrollView吸顶效果

react-native ScrollView吸顶效果

作者: MasterPaul | 来源:发表于2019-04-23 11:08 被阅读0次
    QQ20190423-105919-HD.gif

    原理在屏幕外部渲染一个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,
        },
    });
    
    
    

    相关文章

      网友评论

          本文标题:react-native ScrollView吸顶效果

          本文链接:https://www.haomeiwen.com/subject/nawmgqtx.html