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
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
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
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
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