30-days-of-react-native源碼分析

Github地址

入口-index.ios.js

Swiper插件

import Swiper from 'react-native-swiper';
<Swiper height={150} showsButtons={false} autoplay={true}  activeDot={}>
 //Todo
</Swiper>

Day01 - A stopwatch

設(shè)置頂部狀態(tài)欄

import {StatusBar } from 'react-native';
...
componentDidMount() {
    StatusBar.setBarStyle(0);
  }

Day02 - A weather app

Day03 - Twitter

createAnimatedComponent使得任何一個React組件支持動畫派近。用它來創(chuàng)建Animated.View等等查刻。
加載完成之后頁面圖標(biāo)放大淡出動畫:

const AnimatedIcon = Animated.createAnimatedComponent(Icon);
......
componentDidMount() {
    Animated.timing(
       this.state.transformAnim,    
       {toValue: 50,
        duration: 1200,
        delay:2000,
        easing: Easing.elastic(2),
      },          
    ).start();
    Animated.timing(         
       this.state.opacityAnim,    
       {toValue: 0,
        duration: 800,
        easing: Easing.elastic(1),
        delay:2200,
      },          
     ).start();
    setTimeout(() => {
      this.props.hideThis();
    }, 3300);              
  }

  render () {
    return(
      <Animated.View style={[styles.entrance,{opacity:this.state.opacityAnim}]}>
        <AnimatedIcon size={60} style={[styles.twitter,{transform:[{scale:this.state.transformAnim}]}]} name="logo-twitter"></AnimatedIcon>
      </Animated.View>
    )
  }

scrollView下拉刷新

 <ScrollView
      refreshControl={
          <RefreshControl
              //決定加載進(jìn)去指示器是否為活躍狀態(tài)及穗,也表明當(dāng)前是否在刷新中
              refreshing={this.state.isRefreshing}  
              //當(dāng)視圖開始刷新的時候調(diào)用
              onRefresh={()=>this._onRefresh()}
              // iOS平臺適用  設(shè)置加載進(jìn)度指示器的顏色
              tintColor="red" 
          />
        }
      >
           ......
</ScrollView>

Day04 - Cocoapods

Day05 - Find my location

MapView組件在React Native0.42以后已被淘汰苇经,使用react-native-maps模塊替代理卑。

Day06 - Spotify

import Video from 'react-native-video';

Day07 - Moveable Circle

手勢系統(tǒng)——拖拽組件

class MoveableCircle extends Component{
  constructor() {
    super();
    this.state = {
      color: "rgba(255,255,255,0.7)",
    };
  }

  // 初始left值
  _previousLeft = Util.size.width/2-40;
  // 初始top值
  _previousTop = Util.size.height/2-50;
  //最大top值
  _maxTop = Util.size.height-110;
  //最大left值
  _maxLeft = Util.size.width-98;
  _circleStyles = {};
  //http://stackoverflow.com/questions/32721630/javascript-syntax-null
  circle = (null : ?{ setNativeProps(props: Object): void });

  _updatePosition() {
    this.circle && this.circle.setNativeProps(this._circleStyles);
  }

  _endMove(evt, gestureState) {
    this._previousLeft += gestureState.dx;
    this._previousTop += gestureState.dy;
    this.setState({
      color: "rgba(255,255,255,0.7)"
    });
  }

  componentWillMount() {
    this._panResponder = PanResponder.create({
        //要求成為響應(yīng)者:
        onStartShouldSetPanResponder: (evt, gestureState) => true,
        onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
        onMoveShouldSetPanResponder: (evt, gestureState) => true,
        onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

        // 開始手勢操作央拖。給用戶一些視覺反饋申尼,讓他們知道發(fā)生了什么事情垮卓!
        onPanResponderGrant: (evt, gestureState) => {
          this.setState({
            color: "white",
          })
        },

        onPanResponderMove: (evt, gestureState) => {
            // 最近一次的移動距離為gestureState.move{X,Y}
            // 從成為響應(yīng)者開始時的累計手勢移動距離為gestureState.d{x,y}
           this._circleStyles.style.left = this._previousLeft + gestureState.dx;
           this._circleStyles.style.top = this._previousTop + gestureState.dy;
           if (this._circleStyles.style.left<0) {
              this._circleStyles.style.left = 0;
           };
           if (this._circleStyles.style.top<5) {
              this._circleStyles.style.top = 5;
           };
           if (this._circleStyles.style.left>this._maxLeft) {
              this._circleStyles.style.left = this._maxLeft;
           };
           if (this._circleStyles.style.top>this._maxTop) {
              this._circleStyles.style.top = this._maxTop;
           };
           this._updatePosition();
        },
        onPanResponderTerminationRequest: (evt, gestureState) => true,

        // 用戶放開了所有的觸摸點,且此時視圖已經(jīng)成為了響應(yīng)者师幕。
        // 一般來說這意味著一個手勢操作已經(jīng)成功完成粟按。
        onPanResponderRelease: (evt, gestureState) => this._endMove(evt, gestureState),
        // 另一個組件已經(jīng)成為了新的響應(yīng)者,所以當(dāng)前手勢將被取消霹粥。
        onPanResponderTerminate: (evt, gestureState) => this._endMove(evt, gestureState),
    });

    this._circleStyles = {
      style: {
        left: this._previousLeft,
        top: this._previousTop,
      },
    };

  }

  componentDidMount() {
    this._updatePosition();
  }

  render() {
    return(
      <View ref={(circle) => {this.circle = circle;}} style={styles.MoveableCircle} {...this._panResponder.panHandlers}>
        <Icon ref="baseball" name="ios-baseball" color={this.state.color} size={120}></Icon>
      </View>
    )
  }
}

Day08 - Swipe Left Menu

手勢系統(tǒng)——DrawerNavigator(??????)

Day09 - Twitter Parallax View

手勢系統(tǒng)——位置灭将、尺寸、透明度對著拖動而漸變(????????)

class TwitterUser extends Component{
    constructor() {
        super();
        this.state = {
            scrollEnabled: false, //scrollView是否可以滾動(scrollView與最外層view只有一個可以滾動)
            scale: 1,             //圖標(biāo)的初始scale值
            iconTop: 95,          //圖標(biāo)的初始top值
            bannerTop:0,          //banner的初始top值
            opacity:0,            //view的初始o(jì)pacity值
        };

        this._scrollEnabled = false; //scrollView是否可以滾動

        this._previousTop = 0;  //上一次拖動之后的最外層view的top值
        this._iconTop = 95;     //上一次拖動之后圖標(biāo)的top值
        this._scale = 1;        //上一次拖動之后圖標(biāo)的scale值
        this._bannerTop = 0;    //上一次拖動之后banner的top值
        this._opacity = 0;      //上一次拖動之后banner的opacity值
        this._minTop = -192;    //最外層view的最小top值
        this._userStyle = {};   //最外層view的style樣式
        this.user = (null : ?{ setNativeProps(props: Object): void }); //對最外層view進(jìn)行flow類型檢查
    }

    //最外層view作為手勢的響應(yīng)者后控,使用setNativeProps直接修改屬性
    _updatePosition() {
       this.user && this.user.setNativeProps(this._userStyles);
    }

    //手指松開當(dāng)前最外層view的響應(yīng)者庙曙,或者有其他組件成為新的響應(yīng)者時,執(zhí)行該函數(shù)
    _endMove(evt, gestureState) {
        //使用最新的top值賦值給this._previousTop
        this._previousTop = this._userStyles.style.top;
    }

    componentWillMount() {
        //組件將要渲染時浩淘,創(chuàng)建手勢系統(tǒng)
        this._panResponder = PanResponder.create({
            //要求成為響應(yīng)者:
            onStartShouldSetPanResponder: (evt, gestureState) => true,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
            onMoveShouldSetPanResponder: (evt, gestureState) => {
                return gestureState.dy/gestureState.dx!=0;
            },
            // 開始手勢操作捌朴。
            onPanResponderGrant: (evt, gestureState) => {
                //給用戶一些視覺反饋,讓他們知道發(fā)生了什么事情张抄!
                // gestureState.{x,y}0 現(xiàn)在會被設(shè)置為0
            },
            onPanResponderMove: (evt, gestureState) => {
                // 最近一次的移動距離為gestureState.move{X,Y}
                // 從成為響應(yīng)者開始時的累計手勢移動距離為gestureState.d{x,y}
                // 外層view的top值為0 + gestureState.dy   注意gestureState.dy為負(fù)值
                this._userStyles.style.top = this._previousTop + gestureState.dy;
                //圖標(biāo)的尺寸scale
                this._scale = 1 + this._userStyles.style.top/162.5;
                //圖標(biāo)的top值
                this._iconTop = 95 - this._userStyles.style.top/4.16;
                //banner的top值
                this._bannerTop = 0;
                //view的opacity值
                this._opacity = 0;
                this._scrollEnabled = false;

                if (this._userStyles.style.top< -62.5) {
                    this._scale = 0.6;
                    this._iconTop = 110;
                    this._bannerTop = -this._userStyles.style.top-62.5;
                    //Math.pow(x, y)得到x的y次冪
                    this._opacity = Math.pow((-this._userStyles.style.top-62.5)/129.5,0.5)
                };
                if (this._userStyles.style.top>0) {
                    this._userStyles.style.top = 0;
                    this._scale = 1;
                    this._iconTop = 95
                }
                if (this._userStyles.style.top < this._minTop) {
                    this._userStyles.style.top = this._minTop;
                    this._opacity = 1;
                    this._bannerTop = 129.5;
                    this._scrollEnabled = true;
                };
                this.setState({
                    scrollEnabled: this._scrollEnabled,
                    scale: this._scale,
                    iconTop: this._iconTop,
                    bannerTop: this._bannerTop,
                    opacity: this._opacity
                });
                this._updatePosition();
            },
            onPanResponderTerminationRequest: (evt, gestureState) => true,
            // 用戶放開了所有的觸摸點砂蔽,且此時視圖已經(jīng)成為了響應(yīng)者。
            // 一般來說這意味著一個手勢操作已經(jīng)成功完成署惯。
            onPanResponderRelease: (evt, gestureState) => this._endMove(evt, gestureState),
            // 另一個組件已經(jīng)成為了新的響應(yīng)者左驾,所以當(dāng)前手勢將被取消。
            onPanResponderTerminate: (evt, gestureState) => this._endMove(evt, gestureState),
            onShouldBlockNativeResponder: (event, gestureState) => true,
        });

        this._userStyles = {
            style: {
                top: this._previousTop,
            },
        };
    }

    componentDidMount() {
        this._updatePosition();
    }

    render () {
        let panProps = this.state.scrollEnabled?{}:{...this._panResponder.panHandlers};
        return(
            <View ref={(user) => {this.user = user}} style={styles.userContainer} {...panProps}>
                 <View style={styles.userPanel}>
                     <Image style={[styles.banner,{top: this.state.bannerTop}]} source={{uri:'banner'}} />
                     <View style={[styles.iconContainer,{top:this.state.iconTop,transform:[{scale:this.state.scale}]}]}>
                        <Image style={styles.icon} source={{uri:"icon"}}></Image>
                     </View>
                     <View style={styles.userControl}>
                        <TouchableHighlight style={styles.controlIcon}>
                            <Icon name="ios-settings" color="#8999a5" size={20}></Icon>
                         </TouchableHighlight>
                        <TouchableHighlight style={styles.controlBtn}>
                          <Icon name="ios-people" color="#8999a5" size={20}></Icon>
                        </TouchableHighlight>
                        <TouchableHighlight style={styles.controlBtn2}>
                          <Text style={styles.controlBtnText}>編輯個人資料</Text>
                        </TouchableHighlight>
                     </View>
                     <View style={styles.userInfo}>
                         <Text style={styles.userInfoName}>Github</Text>
                         <Text style={styles.userInfoAccount}>@Github</Text>
                         <View style={styles.userInfoFollow}>
                             <Text style={styles.userInfoFollowing}><Text style={styles.fontEm}>183</Text> 正在關(guān)注</Text>
                             <Text style={styles.userInfoFollower}><Text style={styles.fontEm}>830k</Text> 關(guān)注者</Text>
                         </View>
                     </View>
                      {this.state.bannerTop<=0?<View></View>:<Image style={[styles.banner,{top: this.state.bannerTop}]} source={{uri:'banner'}}></Image>}
                      {this.state.bannerTop<=0?<View></View>:<Image style={[styles.banner,{top: this.state.bannerTop, opacity:this.state.opacity}]} source={{uri:'bannerBlur'}}></Image>}
                      <Text style={{position:"absolute",left:Util.size.width/2-30, fontSize:20, fontWeight:"500", top: this.state.bannerTop+90,opacity:this.state.opacity, backgroundColor:"transparent", color:"#fff"}}>Github</Text>
                      <View style={styles.segment}>
                        <SegmentedControlIOS values={['推文', '媒體', '喜歡']}  selectedIndex={0} tintColor="#2aa2ef"/>
                      </View>
                 </View>
                <ScrollView contentInset={{top:0}} style={styles.detailScroll} scrollEnabled={this.state.scrollEnabled}>
                    <View style={{width:Util.size.width,backgroundColor:"#f5f8fa"}}>
                        <Image style={{width:Util.size.width, height:0.835*Util.size.width, resizeMode:"contain"}} source={{uri:'moreinfo'}}></Image>
                    </View>
                </ScrollView>
            </View>
        )
    }
}

Day10 - Tumblr Menu

Easing的使用

export default class extends Component{
  constructor() {
    super();
    this.state = {
      shift: new Animated.Value(-120),
      show:false,
    };
  }

  _pushMenu() {
    this.setState({
      show: true,
    });

    Animated.timing(         
       this.state.shift,    
       {toValue: Util.size.width === 375? 50:30,
        duration: 200,
        delay:100,
        easing: Easing.elastic(1),
      },          
    ).start();
  }

  _popMenu() {
    Animated.timing(         
       this.state.shift,    
       {toValue: -120,
        duration: 200,
        delay:100,
        easing: Easing.elastic(1),
      },          
    ).start();

    setTimeout(()=>{
      this.setState({
        show: false,
      })
    },500);
  }

  componentDidMount() {
    StatusBar.setBarStyle(1);
  }
  ......
}

Day11 - Using OpenGL with React native

gl-react-native

Day12 - Charts

Day13 - A twitter tweet UI

Day14 - Tinder Like Swipe

react-native-tinder-swipe-cards

Day15 - Time picker

Modal組件可以用來覆蓋包含React Native根視圖的原生視圖(如UIViewController极谊,Activity)诡右。在嵌入React Native的混合應(yīng)用中可以使用Modal。Modal可以使你應(yīng)用中RN編寫的那部分內(nèi)容覆蓋在原生視圖上顯示轻猖。

 <Modal  animationType="slide" transparent={false} visible={this.state.showModal}>
      ······
</Modal>

Day16 - Unlock with gesture

react-native-gesture-password

Day17 - Native search bar and Fuzzy search

react-native-search-bar
f使用 for in 循環(huán)遍歷對象的屬性時帆吻,原型鏈上的所有屬性都將被訪問,推薦總是使用hasOwnProperty方法咙边, 這將會避免原型對象擴(kuò)展帶來的干擾桅锄。

const stateData = {a:1 ,b:2,c:3}
this.states = [];
for (let key in stateData) {
  if (stateData.hasOwnProperty(key)) {
    this.states.push(stateData[key]);
  }
}

Day 18 - Sortable List

手勢系統(tǒng)——拖拽排序(??????????)
代碼
LayoutAnimation的使用
官網(wǎng)文檔
React Native超棒的LayoutAnimation(布局動畫)
React Native API模塊之LayoutAnimation布局動畫詳解

this.animations = {
  duration: 200,
  create: {
    type: LayoutAnimation.Types.linear,
  },
  update: {
    type: LayoutAnimation.Types.linear,
    springDamping: 0.7,
  },
};
...
if (this.finalIndex != this.index) {
  this.index = this.finalIndex;
  this.setState({
    selected: this.finalIndex,
  });
}
LayoutAnimation.configureNext(this.animations);
...
box.setNativeProps({style: {top,left,...shadowStyle}});
LayoutAnimation.configureNext(this.animations);

Day 19 - Unlock app with touchID

react-native-touch-id

Day 20 - Sigle page Reminder

LayoutAnimation的使用

this.animations = {
  duration: 200,
  create: {
    type: LayoutAnimation.Types.linear,
  },
  update: {
    type: LayoutAnimation.Types.linear,
    springDamping: 0.7,
  },
};
......
this.setState({
  listData,
  numOfItems,
});
LayoutAnimation.configureNext(this.animations);

Day21 - Multi page Reminder

Day22 - Google Now

Day23 - Local WebView An example using D3.js

Day 24 - Youtube scrollable tab

react-native-scrollable-tab-view

Day25 - TO BE UPDATED

Day26 - TO BE UPDATED

Day27 - iMessage Gradient

The chat bubble changes its gradient color with its pageY.
react-native-linear-gradient

Day28 - iMessage Image Picker.

Day29 - TO BE UPDATED

Day30 - Push Notification.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琉雳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子友瘤,更是在濱河造成了極大的恐慌翠肘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辫秧,死亡現(xiàn)場離奇詭異束倍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盟戏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門绪妹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人柿究,你說我怎么就攤上這事邮旷。” “怎么了蝇摸?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵婶肩,是天一觀的道長。 經(jīng)常有香客問我貌夕,道長律歼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任啡专,我火速辦了婚禮险毁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘们童。我一直安慰自己畔况,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布慧库。 她就那樣靜靜地躺著问窃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪完沪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天嵌戈,我揣著相機(jī)與錄音覆积,去河邊找鬼。 笑死熟呛,一個胖子當(dāng)著我的面吹牛宽档,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庵朝,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吗冤,長吁一口氣:“原來是場噩夢啊……” “哼又厉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起椎瘟,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤覆致,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肺蔚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體煌妈,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年宣羊,在試婚紗的時候發(fā)現(xiàn)自己被綠了璧诵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡仇冯,死狀恐怖之宿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情苛坚,我是刑警寧澤比被,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站炕婶,受9級特大地震影響姐赡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柠掂,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一项滑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涯贞,春花似錦枪狂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至皇拣,卻和暖如春严蓖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背氧急。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工颗胡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吩坝。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓毒姨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钉寝。 傳聞我的和親對象是個殘疾皇子弧呐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 持續(xù)更新中...... 一套企業(yè)級的 UI 設(shè)計語言和 React 實現(xiàn)闸迷。 https://mobile.ant....
    日不落000閱讀 5,689評論 0 35
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,152評論 25 707
  • 簡短說明 收錄一些好用的RN第三方組件,以方便日常的使用俘枫,大家有什么推薦的也可以跟我說腥沽,我加進(jìn)去。如有冒犯崩哩,可以聯(lián)...
    以德扶人閱讀 43,641評論 44 214
  • 多年之后巡球,你要去那邊境小鎮(zhèn),那里人跡稀少邓嘹,悠長的叫賣聲走街串巷酣栈,不時會有炊煙四起,清晨你走到竹海邊汹押,采摘新鮮的蘑菇...
    半只肥禿閱讀 372評論 0 0
  • 今天在一連聽了好多堂課矿筝,信息量有些大,邊聽邊做筆記棚贾,需要后續(xù)的復(fù)習(xí)窖维、內(nèi)化和應(yīng)用。 1妙痹、利用中午時間铸史,在下班加油站回...
    向著美好奔跑閱讀 176評論 0 0