react-native pad项目

RN中关于侧导航的tab切换设计思想

RN对于pad这块的应用以及组件比较少,项目中想要设计侧导航,但是并没有找到类似侧导航的组件。所以自己做了一个简单的tab切换,但是缺点就是点击的时候切换会比较慢,有待改进。

1. 首先配置json数组,数组中封装了导航需要的标题、icon、选中的icon以及切换的组件。
2. 设置初始状态flag。切换状态时切换成相应的组件。
3. 分别在组件中设置stack/tab路由则可以实现组件内部路由切换。

RN中关于扫码功能

扫码的组件在RN的社区中还是能够找到几种的。同时适配android,ios我只找到了两个: react-native-barcode-scanner-universal和ac-qrcode。安装第一种的时候总会报各种各样的花式错误,所以果断舍弃了第一种,拥抱第二种。

1. npm   install   ac-qrcode   --save
2. 此外还需要安装npm install react-native-camera
3. 需要同react-native-camera link后才能使用:react-native   link
4. 引用组件:
1
2
3
4
5
6
7
8
9
10
11
<QRScannerView
onScanResultReceived={this.barcodeReceived.bind(this)}
renderTopBarView={() => this._renderTitleBar()}
renderBottomMenuView={() => this._renderMenu()}
cornerColor='#34b5ee'
scanBarColor='#34b5ee'
rectWidth={300}
rectHeight={300}
/>

这个组件的好处是可以自定义扫码的样式以及展现形式

RN中禁止屏幕横屏/竖屏显示

android版本

pad的app应用规定只能横屏显示,只需要修改配置文件即可。landscape-横屏,portrait-竖屏。
在AndroidManifest.xml文件中

1
2
3
4
5
<activity
android:name=".DemoActivityt"
android:theme="@android:style/Theme.NoTitleBar"
android:screenOrientation="portrait"
></activity>

另外,android中每次屏幕方向切换时都会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置。要避免在转屏时重启activity,可以通过在androidmanifest.xml文件中重新定义方向(给每个activity加上android:configChanges=”keyboardHidden|orientation”属性),并根据Activity的重写onConfigurationChanged(Configuration newConfig)方法来控制,这样在转屏时就不会重启activity了,而是会去调用onConfigurationChanged(Configuration newConfig)这个方法。
原创:http://www.open-open.com/lib/view/open1328278861750.html

iOS 版本

  1. 在Xcode 中的General>Deployment中修改orientation中相应的项。
  2. 在info.plist>support interface orientation 中不相关的项删除

RN中设置桌面图标及名称

1.名称修改打开android/app/src/main/res/values/strings.xml:

1
2
3
<resources>
<string name="app_name">app名称</string>
</resources>

2.图标修改android\app\src\main\res\mipmap-xxxxxx中直接覆盖图标就可以.

RN中设置启动页避免启动白屏问题

在网络上找到几个关于启动页白屏的插件,其中react-native-splash-screen深得朕心。不过使用的时候要注意对RN的版本限制,React Native >= 0.47.0 use v3.+, for React Native < 0.47.0 use v2.0.0+。因为是pad端所以启动页图片尺寸设置的是屏幕的分辨率

  1. 安装:npm install react-native-splash-screen –save
  2. react-native link react-native-splash-screen
  3. 在MainApplication.java中添加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import com.cboy.rn.splashscreen.SplashScreenReactPackage;
    public class MainApplication extends Application implements ReactApplication {
    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
    new MainReactPackage(),
    new SplashScreenReactPackage() //here
    );
    }
    };
    }
  4. 在MainActivity.java中添加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import android.os.Bundle;
    import com.facebook.react.ReactActivity;
    import com.cboy.rn.splashscreen.SplashScreen; // here
    public class MainActivity extends ReactActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    SplashScreen.show(this); // here
    super.onCreate(savedInstanceState);
    }
    // ...other code
    }
  5. 在js入口文件中导入react-native-splash-screen

    1
    import SplashScreen from 'react-native-splash-screen'
  6. 在app/src/main/res/layout中创建launch_screen.xml文件

    1
    2
    3
    4
    5
    6
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/launch_screen">
    </LinearLayout>
  7. 在app/src/main/res/下创建下列文件夹,并且添加名为launch_screen.png文件:

    1
    2
    drawable-xhdpi
    drawable-xxhdpi
  8. 在js入口文件中使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import SplashScreen from 'react-native-splash-screen'
    export default class WelcomePage extends Component {
    componentDidMount() {
    // do stuff while splash screen is shown
    // After having done stuff (such as async tasks) hide the splash screen
    SplashScreen.hide();
    }
    }

RN中关于文件管理的展示(类似面包屑功能)

主要思想是使用react-native状态控制该显示哪一条数据,刚开始想用react-native导航路由跳转实现,问题是数据不固定,导航不适用。以下为主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/**
* Created by admin on 2017/9/19.
*/
import React,{Component} from 'react'
import {StyleSheet,Dimensions, ScrollView, Text,View,Image, TouchableHighlight, TouchableOpacity,ImageBackground} from 'react-native'
const window = Dimensions.get('window');
const file =
[{
id:0,
title:'体系文件',
children:[
{id:1,title:'文件夹1',children:[
{id:3,title:'文件夹1-1',children:[
{id:5,title:'文件夹1-1-1',children:[]}
]},
{id:4,title:'文件夹1-2',children:[]},
]},
{id:2,title:'文件夹2',children:[]},
]
},
{
id:6,title:'公司文档',children:[]
}];
export default class Crumbs extends Component {
constructor(props) {
super(props);
this.state = {
itemList: file,
showChild:false,
backChild:false,
crumbs:[]
}
}
render(){
var arr = [];
var showItem = function (data,index) {
arr.push(<TouchableOpacity key={data.id} onPress={this.showChild.bind(this,data)}>
<View style={styles.menuText}>
<Image source={require('../img/files.png')}/>
<Text style={{marginLeft:15,fontSize:16}}>{data.title}</Text>
</View>
</TouchableOpacity>)
}.bind(this);
var item = this.state.crumbs.map((item,index)=>{
return <TouchableOpacity key={index} onPress={this.backChild.bind(this,item)}>
<View style={{flexDirection:'row'}}>
<Text style={{textAlignVertical:'center',fontSize:16,paddingLeft:10}}>{item.title.title}</Text>
<Image source={require('../img/crumb-right.png')}/>
</View>
</TouchableOpacity>
},this);
this.state.itemList.map((data)=>{
showItem(data,0)
});
return(
<View style={styles.fileStyle}>
<View style={styles.fileUrl}>
<TouchableOpacity onPress={this.showHome.bind(this)}>
<View style={{flexDirection:'row'}}>
<Text style={{textAlignVertical:'center',fontSize:16,paddingLeft:10}}>主页</Text>
<Image source={require('../img/crumb-right.png')}/>
</View>
</TouchableOpacity>
{item}
</View>
<ScrollView>
<View style={styles.fileContent}>
{this.state.showChild ? this.renderChild(): (this.state.backChild ? this.renderBackChild(): arr)}
</View>
</ScrollView>
</View>
)
}
showChild(data){
this.state.crumbs.push({id:data.id,title:data});
this.setState({showChild:true,childContent:data});
}
showHome(){
this.setState({showChild:false,backChild:false});
for(let i=0;i<this.state.crumbs.length;i++){
this.state.crumbs.splice(0,this.state.crumbs.length);
}
}
backChild(data){
this.setState({backChild:true,backChildContent:data,childContent:data,showChild:false});
for(let i=0;i<this.state.crumbs.length;i++){
if(this.state.crumbs[i].id == data.id){
this.state.crumbs.splice(i+1,this.state.crumbs.length);
}
}
}
renderChild(){
var arr = [];
var child = this.state.childContent;
this.mapChild(child,arr);
return arr
}
mapChild=(data,arr1)=>{
var child = data.children || data;
if(child.length){
child.map(function (m,i) {
arr1.push(<TouchableOpacity key={m.id} style={styles.menuText} onPress={this.showChild.bind(this,m)}>
<Image source={require('../img/files.png')}/>
<Text style={{marginLeft:15,fontSize:16}}>{m.title}</Text>
</TouchableOpacity>)
}.bind(this))
}else{
arr1.push(<View style={styles.noTextContent} key={'id'}>
<Text style={styles.noTextStyle}>没有内容</Text>
</View>)
}
};
renderBackChild(){
var arr = [];
var child = this.state.backChildContent;
this.mapBackChild(child,arr);
return arr
}
mapBackChild(data,arr2){
var child = data.title.children || data.title;
if(child.length){
child.map(function (m,i) {
arr2.push(<TouchableOpacity key={m.id} style={styles.menuText} onPress={this.showChild.bind(this,m)}>
<Image source={require('../img/files.png')}/>
<Text style={{marginLeft:15,fontSize:16}}>{m.title}</Text>
</TouchableOpacity>)
}.bind(this))
}else{
arr2.push(<View style={styles.noTextContent} key={'id'}>
<Text style={styles.noTextStyle}>没有内容</Text>
</View>)
}
}
}
const styles = StyleSheet.create({
fileContent:{
borderColor:'#d5d5d5',
borderWidth:0.5,
backgroundColor:'#fff',
marginTop:-1,
},
fileStyle:{
margin:10,
marginBottom:0,
backgroundColor:'#fff',
height:window.height
},
menuText:{
height:60,
borderBottomColor:'#d5d5d5',
borderBottomWidth:0.5,
paddingLeft:15,
flexDirection:'row',
alignItems:'center'
},
fileUrl:{
height:50,
paddingLeft:10,
backgroundColor:'#f5f5f5',
flexDirection:'row',
alignItems:'center',
borderColor:'#d5d5d5',
borderWidth:0.5,
},
noTextContent:{
height:window.height-50,
},
noTextStyle:{
fontSize:16,
textAlignVertical:'center',
textAlign:'center',
color:'#999',
marginTop:250
}
});

觉得代码量比较多,还有更简单的方法,待改进。

RN中native-echarts组件打包时遇到的问题

使用:

  1. npm install native-echarts –save
  2. 1
    2
    import Echarts from 'native-echarts'
    <Echarts option={alarmBarOption}/>

打包生成apk-release时无法显示统计图表:

1
2
3
4
android release版本通过“把tpl.html文件放在android/app/src/main/assets文件里
修改的是 \node_modules\native-echarts\src\components\Echarts\index.js中的代码,具体如下:
源代码为:source={require('./tpl.html')}
修改为:source={{uri:'file:///android_asset/tpl.html'}}
undefined