sample-calculator
元件:
index.js(進入點)
Controller\RootController.js(根組件)(放置業務邏輯)
View\RootView.js(父組件介面繪製)
View\NumButton.js(子組件介面繪製)
1.index.js
//進入點的程式基本不更動,是固定架構的寫法
//但此處用RootController取代app做為根組件
import {AppRegistry} from 'react-native';
import RootController from './Controller/RootController';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => RootController);
2.RootController.js
//根組件
import React, { Component } from 'react';
//載入view的父元件
import RootView from './../View/RootView';
export default class RootController extends Component{
render(){
//將Controller整個傳入RootView,使其可使用所有在Controller中的屬性或方法
//用ref可在父元件調用子元件的方法和屬性
return (<RootView controller={this} ref="rootView"/>);
}
//按下調換按鈕後執行的動作邏輯
//此處的函式只做呼叫的邏輯(放入參數和執行),真正的程式在view內
change(){
if (this.refs.rootView.isDollarToRMB) {
this.refs.rootView.exchange(false);
}else{
this.refs.rootView.exchange(true);
}
}
//按下計算機的相關按鈕(數字、小數點、運算符號…等)
//真正的程式在view內
click(title){
if (title==="0"||title==="1"||title==="2"||title==="3"||title==="4"
||title==="5"||title==="6"||title==="7"||title==="8"||title==="9"||title===".") {
this.refs.rootView.inputNum(title);
}else if(title==="delete"){
this.refs.rootView.delete();
}else if(title==="C"){
this.refs.rootView.clear();
}else if(title==="-"){
this.refs.rootView.sub();
}else if(title==="+"){
this.refs.rootView.add();
}else if(title==="="){
this.refs.rootView.rate();
}
}
}
3.RootView.js
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
Dimensions,
TouchableHighlight,
Image
} from 'react-native';
import NumButton from './NumButton';
const rate = 6.7;
export default class RootView extends Component{
isDollarToRMB = true;
//參數isDaller是在controller中賦值
exchange(isDaller){
if (!isDaller) {
this.setState({
topTitle:"从人民币",
bottomTitle:"到美元",
topNum:"0$",
bottomNum:"0¥",
});
}
else{
this.setState({
topTitle:"从美元",
bottomTitle:"到人民币",
topNum:"0$",
bottomNum:"0¥",
});
}
this.isDollarToRMB = isDaller;
}
inputNum(title){
let str = this.state.topNum.slice(0,-1);
if (title===".") {
if (str.indexOf(".")===-1) {
if (this.isDollarToRMB) {
this.setState({
topNum:Number(str)+title+"$",
});
}else{
this.setState({
topNum:Number(str)+title+"¥",
});
}
}else{
return;
}
}else{
if (this.isDollarToRMB) {
this.setState({
topNum:Number(str+title)+"$",
});
}else{
this.setState({
topNum:Number(str+title)+"¥",
});
}
}
}
delete(){
let str = this.state.topNum.slice(0,-1);
if (str.length===1) {
if (this.isDollarToRMB) {
this.setState({
topNum:"0$",
});
}else{
this.setState({
topNum:"0¥",
});
}
}else{
if (this.isDollarToRMB) {
this.setState({
topNum:str.slice(0,-1)+"$",
});
}else{
this.setState({
topNum:str.slice(0,-1)+"¥",
});
}
}
}
clear(){
this.setState({
topNum:"0$",
bottomNum:"0¥",
});
}
sub(){
let str = this.state.topNum.slice(0,-1);
if (Number(str)<1) {
return;
}else{
if (this.isDollarToRMB) {
this.setState({
//此處的程式單純將數值減1
topNum:(Number(str)-1).toFixed(2)+"$",
});
}else{
this.setState({
topNum:Number(str).toFixed(2)-1+"¥",
});
}
}
}
add(){
let str = this.state.topNum.slice(0,-1);
if (this.isDollarToRMB) {
this.setState({
topNum:(Number(str)+1).toFixed(2)+"$",
});
}else{
this.setState({
topNum:(Number(str)+1).toFixed(2)+"¥",
});
}
}
rate(){
let str = this.state.topNum.slice(0,-1);
if (this.isDollarToRMB) {
this.setState({
bottomNum:(Number(str)*rate).toFixed(2)+"¥",
});
}else{
this.setState({
bottomNum:(Number(str)/rate).toFixed(2)+"$",
});
}
}
constructor(props){
super(props);
//view內放state
this.state = {
topTitle:"从美元",
topNum:"0$",
bottomTitle:"到人民币",
bottomNum:"0¥",
rootViewStyle:rootViewStyle1,
lineViewHeight:25
};
let titles = ["1","2","3","delete","4","5","6","0","7","8","9",".","C","-","+","="];
//儲存按鈕的jsx
let array = new Array();
for (var i = 1; i <= 16; i++) {
let element;
if (i==4) {
//再把controller及相關屬性往下傳
element = (<NumButton style={this.state.rootViewStyle.buttonStyle} key={i} title={titles[i-1]} model="image" controller={this.props.controller} />);
}else if(i==13||i==16){
element = (<NumButton style={[this.state.rootViewStyle.buttonStyle,{backgroundColor:"rgb(234,86,37)"}]} key={i} title={titles[i-1]} model="text" controller={this.props.controller} />);
}
else{
element = (<NumButton style={this.state.rootViewStyle.buttonStyle} key={i} title={titles[i-1]} model="text" controller={this.props.controller} />);
}
array.push(element);
}
this.buttons = array;
}
render(){
return(
//onLayout觸發切換style(用了效能好,不用也可)
<View style={this.state.rootViewStyle.rootView} onLayout={this._onLayout}>
<View style={this.state.rootViewStyle.screenView}>
<Text style={this.state.rootViewStyle.titleStyle}>{this.state.topTitle}</Text>
<Text style={this.state.rootViewStyle.numberStyle}>{this.state.topNum}</Text>
<View style={this.state.rootViewStyle.exchangeView}>
//按下後觸發controller的change
<TouchableHighlight underlayColor="rgb(234,86,37)" onPress={()=>{
this.props.controller.change();
}}>
<Image style={this.state.rootViewStyle.image} source={require("../src/exchange.png")}/>
</TouchableHighlight>
<View style={this.state.rootViewStyle.lineView}></View>
</View>
<Text style={[this.state.rootViewStyle.titleStyle,{marginTop:5}]}>{this.state.bottomTitle}</Text>
<Text style={this.state.rootViewStyle.numberStyle}>{this.state.bottomNum}</Text>
</View>
<View style={this.state.rootViewStyle.keyboardView}>
//一排四個按鈕
<View style={this.state.rootViewStyle.rowView}>
{
this.buttons.slice(0,4)
}
</View>
<View style={this.state.rootViewStyle.rowView}>
{
this. buttons.slice(4,8)
}
</View>
<View style={this.state.rootViewStyle.rowView}>
{
this.buttons.slice(8,12)
}
</View>
<View style={this.state.rootViewStyle.rowView}>
{
this.buttons.slice(12,16)
}
</View>
</View>
</View>
);
}
//轉換手機方向時,變更style
_onLayout=()=>{
let {width,height} = Dimensions.get("window");
if (width>height) {
this.setState({
rootViewStyle:rootViewStyle2,
lineViewHeight:0
});
}else{
this.setState({
rootViewStyle:rootViewStyle1,
lineViewHeight:25
});
}
}
}
//手機垂直擺放的格式
let rootViewStyle1 = StyleSheet.create({
screenView:{
backgroundColor:"rgb(234,86,37)",
//佔畫面1/3
flex:1
},
keyboardView:{
backgroundColor:'rgb(38,41,42)',
//佔畫面2/3
flex:2
},
rootView:{
flex:1
},
titleStyle:{
marginRight:15,
fontSize:17,
textAlign:'right',
color:"white",
marginTop:25
},
numberStyle:{
fontSize:30,
textAlign:'right',
marginRight:15,
marginTop:5,
color:'white'
},
exchangeView:{
height:20,
flexDirection:'row'
},
image:{
width:18,
height:18,
marginTop:1,
marginLeft:100,
},
//橫向直線
lineView:{
height:1,
backgroundColor:'white',
flex:1,
marginTop:9,
marginLeft:20
},
rowView:{
flex:1,
flexDirection:'row'
},
buttonStyle:{
flex:1,
}
});
let rootViewStyle2 = StyleSheet.create({
screenView:{
backgroundColor:"rgb(234,86,37)",
flex:3
},
keyboardView:{
backgroundColor:'rgb(38,41,42)',
flex:5
},
rootView:{
flex:1
},
titleStyle:{
marginRight:15,
fontSize:13,
textAlign:'right',
color:"white",
marginTop:5
},
numberStyle:{
fontSize:22,
textAlign:'right',
marginRight:15,
marginTop:2,
color:'white'
},
exchangeView:{
height:20,
flexDirection:'row'
},
image:{
width:14,
height:14,
marginTop:1,
marginLeft:300,
},
lineView:{
height:1,
backgroundColor:'white',
flex:1,
marginTop:7,
marginLeft:20
},
rowView:{
flex:1,
flexDirection:'row'
},
buttonStyle:{
flex:1,
}
});
4.NumButton.js
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
TouchableHighlight,
Image
} from 'react-native';
export default class NumButton extends Component{
render(){
//當按下的按鈕是文字格式時,render出的jsx語法
if (this.props.model === "text") {
return(
<TouchableHighlight style={[this.props.style,numberStyle.container]} onPress={()=>{
this.props.controller.click(this.props.title);
}}>
<Text style={numberStyle.text}>{this.props.title}</Text>
</TouchableHighlight>
);
}else{
//按下是圖片時
return(
<TouchableHighlight style={[this.props.style,numberStyle.container]} onPress={()=>{
this.props.controller.click(this.props.title);
}}>
<View style={numberStyle.imageView}>
<Image style={numberStyle.imageStyle} source={require("../src/delete.png")}/>
</View>
</TouchableHighlight>
);
}
}
}
let numberStyle = StyleSheet.create({
container:{
flexDirection:'row'
},
text:{
color:"white",
textAlign:'center',
flex:1,
alignSelf:'center',
fontSize:27
},
imageView:{
flexDirection:'row',
flex:1,
justifyContent:'center'
},
imageStyle:{
alignSelf:'center',
}
});
Last updated