react-native 编写的一个点击展开,下拉刷新案例

下面这个主要是一个微信分享的页面,包含两个tab,主要做的是第二个就爱不正经的tab页面,主要包含功能,朋友圈配图默认展示两张图片,下面又展开按钮,可以展开可以收起。朋友圈配图类似一个两列的瀑布流,包含下拉刷新功能,上拉加载功能。下面代码有些是引用公司的一些组件库,可能直接复制代码跑不通,接口跑不通,可以自己制造假数据,不过基本的逻辑还是可以参考的。

image.png
image.png
image.png
/**
 * Created by lyy45532 on 17/8/9.
 */
'use strict';
import React, { Component } from 'react';
import {
    View,
    Text,
    StyleSheet,
    TouchableOpacity,
    Image,
    ScrollView,
    Platform,
    RefreshControl,
    AsyncStorage,
    NativeModules
} from 'react-native';
import {
  TOKEN_NAME,
  Updateareaphone,
  GetCircleCoverAPI,
  GetIllustrationAPI
} from '../../Common/services/Interfaces';
import {XGFetch} from '../../Common/services/XGFetch';
import PlatformIndexView from './MyTextView';
import HeadNavBar from '../../Common/components/HeadNavBar';
import { IconData } from '../../Common/style/IconBase';
import { WinStyle } from '../../Common/style/ComStyle';
//toast提示组件
import {ToastShow} from '../../Common/components/ToastShow';
import Loading from '../../Common/components/Spinner';
//分享弹窗组件
import ShareComponent from '../../Common/components/ShareComponent';
import {wakeUpWechat} from '../../Common/services/rnModuleFn';
const rnModule = Platform.OS == 'android' ?  NativeModules.ToastModule : NativeModules.RNModule;
const winWidth = WinStyle.WinWidth,
      winHeight = WinStyle.WinHeight,
      imgScale = winWidth / 750;
const PicW = (winWidth - 30)/2;
const btnList = [
        {
            name:'严选好素材',
            tabId:1
        },
        {
            name:'就爱不正经',
            tabId:2
        }
      ];
export default class NewShare extends Component{
    constructor(props) {
      super(props);
      //就爱不正经
      this.leftHeight = 0;
      this.rightHeight = 0;
      this.leftArr = [];
      this.rightArr = [];
      this.totalSize = 1;
      this.state = {
        tabId:1,
        IsAllData:false,
        isLoad:true,
        isLoad1:true,
        isRefreshingBad: false,
        IsClickImg:false,
        IsMore:false,
        errorStatus:false,
        errorStatus1:false,
        CoverImgList:[],
        myImgList:[],
        currentSize:1,
      };
      let {navigate,goBack} = this.props.navigation;
    }
    componentDidMount(){
      // 获取用户信息
      AsyncStorage.getItem(TOKEN_NAME).then( (storeData) => {
          storeData = JSON.parse(storeData);
          this.storeData = storeData;
          setTimeout(() => {
            this.getMyPicList();
            this.getMyCoverList();
          },500)
      });
    }
    //返回上一页
    backToMain(){
      this.props.navigation.goBack();
    }
    tanBtn(tabId){
        this.setState({
            tabId:tabId
        })
    }
    //获取朋友圈封面图
    getMyCoverList(){
      let url = GetCircleCoverAPI.get({
            Token:this.storeData.Token,
        });
      console.log(url);
        XGFetch(url,(json)=>{
            let result = null;
            try {
                result = JSON.parse(json.result);
            } catch (e) {
                result = {};
                this.setState({
                  errorStatus1:true,
                  isLoad1:false
                })
            }
            // 出现错误
            if (json.gwerror > 0) {
                this.setState({
                  errorStatus1:true,
                  isLoad1:false
                })
                return;
            }
            if(result.ResCode != 1000){
                this.setState({
                  errorStatus1:true,
                  isLoad1:false
                })
                return;
            }
            this.setState({
              CoverImgList:result.PicList,
              isLoad1: false,
              errorStatus1:false
            })

        },(err)=>{
            this.setState({
              errorStatus1:true,
              isLoad1:false
            })
        })
    }
    //获取朋友圈配图图片列表
    getMyPicList(){
      let url = GetIllustrationAPI.get({
            Token:this.storeData.Token,
            PageIndex:this.state.currentSize,
            Pagesize:10
        });
      console.log(url);
        XGFetch(url,(json)=>{
            let result = null;
            try {
                result = JSON.parse(json.result);
            } catch (e) {
                result = {};
                this.setState({
                  errorStatus:true,
                  isLoad:false
                })
            }
            // 出现错误
            if (json.gwerror > 0) {
                this.setState({
                  errorStatus:true,
                  isLoad:false
                })
                return;
            }
            if(result.ResCode != 1000){
                this.setState({
                  errorStatus:true,
                  isLoad:false
                })
                return;
            }
            this.totalSize = Math.ceil(result.TotalCount/10);
            result.PicList.map((item,i) => {
                const picH = PicW * item.ImgHeight / item.ImgWidth;
                item.ImgWidth = PicW;
                item.ImgHeight = picH;
                if(this.leftHeight <= this.rightHeight){
                    this.leftArr.push(item);
                    this.leftHeight += picH + 10;
                } else {
                    this.rightArr.push(item);
                    this.rightHeight += picH + 10;
                }
            });
            this.setState({
              myImgList:result.PicList,
              isLoad: false,
              isRefreshingBad:false,
              errorStatus: false
            })
        },(err)=>{
            this.setState({
              errorStatus:true,
              isLoad:false
            })
        })
    }
    //滚到底部事件
    scrollFn(e){
      let { contentOffset,contentSize,layoutMeasurement } = e.nativeEvent;
      let [ offsetY,visibleH,contentH ]  = [ contentOffset.y,layoutMeasurement.height,contentSize.height ];
      //距离底部40距离的时候开始加载第二页
      if (contentH - offsetY <= visibleH + 40 && this.lastContentHeight != contentH && this.state.currentSize < this.totalSize) {
        this.lastContentHeight = contentH;
        this.setState({
          currentSize:this.state.currentSize + 1,
          isRefreshingBad:false,
        },() => {
          //重新获取数据
          this.getMyPicList();
        })
      }
      if(this.state.currentSize >= this.totalSize && !this.state.IsAllData){
        this.setState({
          IsAllData: true
        })
      }
    }
    //下拉刷新事件
    onRefreshBad(){
      this.setState({
        isRefreshingBad:true,
        IsMore:false,
        IsAllData:false,
        currentSize:1,
      },()=>{
          this.leftArr = [];
          this.rightArr = [];
          this.leftHeight = 0;
          this.rightHeight = 0;
          this.lastContentHeight = null;
          this.getMyPicList();
          this.getMyCoverList();
      });
    }
    //点击加载更多朋友圈图片
    getCoverImg(){
      this.setState({
        IsMore: !this.state.IsMore
      })
    }
    //点击图片看弹窗详情
    showBigImgForShare(ImgUrl){
      this.setState({
        showBigImgUrl:ImgUrl,
        IsClickImg:true
      })
    }
    //网络错误,点击重试
    badRetry(){
      this.setState({
        isLoad: true,
        errorStatus:false,
        isLoad1: true,
        errorStatus1:false
      },() => {
        this.getMyPicList();
        this.getMyCoverList();
      })
    }
    //点击保存图片
    collectImg(ImgUrl){
      rnModule.saveImage([ImgUrl],(event)=>{
            if(!event){
              ToastShow('保存失败,请重新保存');
              talkingData('xg_fail_wechat_save_picture','',{'employee':this.storeData.JobNumber,'error': '图片保存失败'});
            }else{
              ToastShow('图片已保存到本地相册');
            }
        })
    }
    //点击分享
    shareImg(ImgUrl){
      alert(ImgUrl)
    }
    //渲染列表
    returnScrollContent(){
        if (this.state.isLoad || this.state.isLoad1) {
          return(<View style={styles.loadingStyleBad}>
                    <Loading />
                  </View>)
        }
        if (this.state.errorStatus || this.state.errorStatus1) {
          return(<TouchableOpacity activeOpacity={0.8} style={styles.loadingStyleBad} onPress={this.badRetry.bind(this)}>
                    <Text>网络错误,请点击重试</Text>
                 </TouchableOpacity>)
        }
        return (<View style={{flex:1}}>
                  {
                    this.state.CoverImgList && this.state.CoverImgList.length > 0 ?
                    (<View style={{flex:1}}>
                        <View style={styles.coverImgBoxBad}>
                            <Image source={require('../../images/wechatshare/titleImg.png')} style={styles.ImgTitelBad}/>
                            <Text style={styles.titleTextStyleBad}>朋友圈封面图</Text>
                        </View>
                        <View style={{flexDirection:'row',flexWrap:'wrap'}}>

                            {
                                this.state.CoverImgList.map((item,i) => {
                                   return(
                                    (i>=2 && !this.state.IsMore) ? null :
                                    <TouchableOpacity activeOpacity={0.8} key={'picback'+i} style={[styles.clickImgBad,{marginLeft:i%2===0 ? 0 : 10,marginTop:i>1 ? 10 : 0}]} onPress={this.showBigImgForShare.bind(this,item)}>
                                        <Image source={{uri:item}}
                                               style={[styles.clickImgBad,{borderRadius:4}]} />
                                    </TouchableOpacity>
                                   )
                                })
                            }
                        </View>
                        {
                          this.state.CoverImgList.length > 2 ?
                          (
                            <TouchableOpacity activeOpacity={0.8} style={styles.downRowBtnBad} onPress={this.getCoverImg.bind(this)}>
                                <Image source={require('../../images/wechatshare/downRow.png')} style={[styles.rowBad,{transform:!this.state.IsMore ? [{rotate:'0deg'}] :[{rotate:'180deg'}]}]}/>
                            </TouchableOpacity>
                            ):null
                        }
                      </View>) : null
                  }
                  {
                    this.state.myImgList && this.state.myImgList.length > 0 ?
                    (<View style={{flex:1}}>
                        <View style={styles.showPicTitelBoxBad}>
                            <Image source={require('../../images/wechatshare/titleImg.png')} style={styles.ImgTitelBad}/>
                            <Text style={styles.titleTextStyleBad}>朋友圈配图</Text>
                        </View>
                        <View style={styles.boxModelBad}>
                          <View style={{width:PicW,marginRight:5}}>
                              {
                                  this.leftArr.map((item,i) => {
                                      return(
                                          <TouchableOpacity key={'leftImg' + i} style={{marginTop: i > 0 ? 10 : 0}} activeOpacity={0.8} onPress={this.showBigImgForShare.bind(this,item.ImgUrl)}>
                                              <Image source={{uri:item.ImgUrl}} style={{width:item.ImgWidth,height:item.ImgHeight,borderRadius:4}}/>
                                          </TouchableOpacity>
                                          )
                                  })
                              }
                          </View>
                          <View style={{width:PicW,marginLeft:5}}>
                              {
                                  this.rightArr.map((item,i) => {
                                      return(
                                          <TouchableOpacity key={'rightImg' + i} style={{marginTop: i > 0 ? 10 : 0}} activeOpacity={0.8} onPress={this.showBigImgForShare.bind(this,item.ImgUrl)}>
                                              <Image source={{uri:item.ImgUrl}} style={{width:item.ImgWidth,height:item.ImgHeight,borderRadius:4}}/>
                                          </TouchableOpacity>
                                          )
                                  })
                              }
                          </View>

                          {
                            this.state.IsAllData ?
                            (<View style={styles.allDataBad}>
                                <Text>====到底啦,没有更多数据了====</Text>
                            </View>):null
                          }

                        </View>
                      </View>) : null
                  }
                </View>)
    }
    //当点击图片的时候渲染弹窗
    renderDialog(){
       return(
          this.state.IsClickImg ?
          (<View style={styles.dialogBoxBad}>
              <View style={styles.dialogBgBad}>
              </View>
              <View style={styles.dialogContentBad}>
                  <View style={styles.dailogTopBoxBad}>
                      <View style={styles.dialogImgBoxBad}>
                         <Image resizeMode={'contain'} source={{uri:this.state.showBigImgUrl}} style={styles.dailogImgStyleBad}/>
                      </View>
                      <View style={styles.dailogTextBoxBad}>
                        <TouchableOpacity activeOpacity={0.8} style={styles.collectBoxBad} onPress={this.collectImg.bind(this,this.state.showBigImgUrl)}>
                          <Text style={{fontSize:16,color:'#333'}}>保存图片</Text>
                        </TouchableOpacity>
                        <TouchableOpacity activeOpacity={0.8} style={[styles.collectBoxBad,styles.shareBoxBad]} onPress={this.shareImg.bind(this,this.state.showBigImgUrl)}>
                          <Text style={{fontSize:16,color:'#f0f0f0'}}>分享</Text>
                        </TouchableOpacity>
                      </View>
                  </View>
                  <TouchableOpacity style={styles.closeDialogBoxBad} onPress={()=>{this.setState({IsClickImg:false})}}>
                      <View style={styles.closeBtnLeftBad}></View>
                      <View  style={styles.closeBtnRightBad}></View>
                  </TouchableOpacity>
              </View>

            </View>):null
        )
    }
    render(){
        return(
                <View style={styles.wrapper}>
                  {this.renderDialog()}
                  <HeadNavBar
                      title='素材'
                      noiOSHeadColor
                      leftIcon={IconData.newBackIcon}
                      leftIconPress={this.backToMain.bind(this)}
                  />
                  <View style={{height:44,flexDirection:'row'}}>
                    {
                      btnList.map((item,i) => {
                          return (
                                <TouchableOpacity style={styles.tabBtn} activeOpacity={1} key={i} onPress={this.tanBtn.bind(this,item.tabId)}>
                                    <View style={[styles.tabTextBox,{borderBottomColor:this.state.tabId === item.tabId ? '#3ac569' : '#f6f6f6'}]}>
                                        <Text style={{fontSize:14,color:this.state.tabId === item.tabId ?  '#3ac569' :'#333'}}>{item.name}</Text>
                                    </View>
                                </TouchableOpacity>
                              )
                      })
                    }
                  </View>
                  {
                    this.state.tabId === 1 ?
                    (<View style={{flex:1,justifyContent:'center',alignItems:'center'}}><Text>严选好素材页面</Text></View>):
                    (<ScrollView
                        onScroll={this.scrollFn.bind(this)}
                        refreshControl={
                                      <RefreshControl
                                        refreshing={this.state.isRefreshingBad}
                                        onRefresh={this.onRefreshBad.bind(this)}
                                        colors={['#3ac569']}
                                        tintColor={'#3ac569'}
                                        progressBackgroundColor='#fff' />
                                      }
                        scrollEventThrottle={200}
                        style={{flex:1,marginLeft:10,marginRight:10}}>
                        {
                          this.returnScrollContent()
                        }
                     </ScrollView>)
                  }
                </View>
            )
    }
}
const styles = StyleSheet.create({
      wrapper: {
        backgroundColor: '#fff',
        flex: 1,
        position:'relative',
      },
      tabBtn: {
        flex:1,
        backgroundColor:'#f6f6f6',
        paddingLeft:30,
        paddingRight:30
      },
      tabTextBox: {
        borderBottomWidth:2,
        flex:1,
        justifyContent:'center',
        alignItems:'center',
      },
      downRowBtnBad: {
        width: winWidth - 20,
        height:12,
        paddingTop:20,
        paddingBottom:12,
        justifyContent:'center',
        alignItems:'center'
      },
      boxModelBad: {
        flex:1,
        flexDirection:'row',
        flexWrap:'wrap'
      },
      loadingStyleBad: {
        height: Platform.OS == 'ios' ? winHeight - 108 : winHeight - 88,
        alignItems:'center',
        justifyContent:'center'
      },
      titleTextStyleBad: {
        position:'absolute',
        fontSize:16,
        color:'#333'
      },
      dialogBoxBad: {
        flex:1,
        position:'absolute',
        left:0,
        top:0,
        bottom:0,
        right:0,
        zIndex:1,
        justifyContent:'center',
        alignItems:'center'
      },
      dialogBgBad: {
        width:winWidth,
        height:winHeight,
        backgroundColor:'#333',
        opacity:0.7,
        position:'absolute',
        top:0,left:0
      },
      dialogImgBoxBad: {
        height:700 * imgScale,
        paddingTop:20,
        width:winWidth-40,
        borderTopLeftRadius:4,
        borderTopRightRadius:4,
        overflow:'hidden'
      },
      collectBoxBad: {
        width:(winWidth-80)/2,
        height:40,
        borderWidth:1,
        borderColor:'#ccc',
        borderRadius:4,
        marginLeft:15,
        justifyContent:'center',
        alignItems:'center'
      },
      closeDialogBoxBad: {
        width:44,
        height:44,
        borderWidth:1,
        borderRadius:22,
        borderColor:'#fff',
        position:'absolute',
        bottom:0,
        justifyContent:'center',
        alignItems:'center',
      },
      coverImgBoxBad: {
        height:50,
        justifyContent:'center',
        alignItems:'center'
      },
      ImgTitelBad: {
        width:270,
        height:4
      },
      clickImgBad: {
        width: (winWidth - 30)/2 ,
        height: (winWidth - 30)/2
      },
      rowBad: {
        width:13,
        height:12
      },
      showPicTitelBoxBad: {
        height:50,
        alignItems:'center',
        justifyContent:'center'
      },
      allDataBad: {
        height:44,
        width:winWidth-20,
        justifyContent:'center',
        alignItems:'center'
      },
      dialogContentBad: {
        position:'relative',
        paddingBottom:70,
        justifyContent: 'center',
        alignItems: 'center'
      },
      dailogTopBoxBad: {
        height:900 * imgScale,
        width:winWidth-40,
        borderRadius:4,
        backgroundColor:'#fff'
      },
      dailogImgStyleBad: {
        height:700 * imgScale - 20,
        width:'100%'
      },
      dailogTextBoxBad: {
        flex:1,
        height:100,
        flexDirection:'row',
        justifyContent:'center',
        alignItems:'center'
      },
      shareBoxBad: {
        borderColor:'#ff674b',
        marginLeft:10,
        backgroundColor:'#ff674b'
      },
      closeBtnLeftBad: {
        backgroundColor:'#fff',
        width:30,
        height:1,
        transform:[{rotate:'45deg'},
        {translateY:1},{translateX:1}]
      },
      closeBtnRightBad: {
        backgroundColor:'#fff',
        width:30,
        height:1,
        transform:[{rotate:'-45deg'}]
      }
})

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,047评论 25 707
  • 人生就是不断的放下 但我最放不下的 还是你 一个人的独白 此刻所在地标——北京。 一觉醒来,气温17度,夏天走了。...
    丑胖纸_阅读 460评论 0 0
  • 好不容易盼来了星期五的夜晚,希齐大饱眼福——看了会儿电视,玩了阵子游戏。爸爸洗澡,希齐抢先挨妈妈睡下,兄...
    星芳希齐阅读 220评论 0 1
  • 1
    飞雪连天射白鹿阅读 187评论 0 0
  • for (int i = 0; i <5; i++) {// //执行5次// for (in...
    晨曦_hero阅读 132评论 0 1