編輯:關於Android編程
上周把基於
Redux
的單頁應用開發完 緊接著就開始了ReactNative
的開發。真的快得不可思議,只花了一周時間,我們兩個人就分工把APP也開發完了,並且同時兼容IOS
操作系統和Android
操作系統。內部測試了一輪,流暢性和用戶體驗方面也都相當給力! 接下去幾篇依次介紹項目開發中領悟的技巧和遇到的坑。
和React
開發的單頁應用不同,ReactNative
開發不需要依賴webpack
,facebook
已經提供的一套基於NodeJS
的轉換和運行工具,這裡不多做介紹。項目的架構如下:
|---- project
|---- android // android外殼
|---- ios // ios外殼
|---- node_modules // 項目依賴的node模塊
|---- app // 本項目的js代碼
|---- actions // Redux的actions
|---- assets // 項目使用的icon
|---- components // 項目自定義的組件
|---- containers // 項目的容器頁面
|---- mixins // 全局使用的工具方法
|---- modules // 全局使用的自定義模塊
|---- reducers // Redux的reducers
|---- configureStore.js // Redux的store配置
|---- index.js // APP入口頁面
|---- index.ios.js // android入口
|---- index.android.js // ios入口
|---- packge.json // 項目包信息
對
Redux
不清楚的童鞋可以出門看我之前的《基於Redux的單頁應用開發總結》 。其實除了路由,其他和單頁應用的結構差別不大。
ReactNative
開發離不開NodeJS
的支持,相比單頁應用,這裡依賴的模塊比較少,除了Redux
相關的模塊,其他都是項目中用到的三方組件。
"dependencies": {
"@remobile/react-native-toast": "^1.0.4", // 用於錯誤提示的小彈窗
"base-64": "^0.1.0",
"react": "^0.14.8",
"react-native": "^0.25.1",
"react-native-animatable": "^0.6.0", // 動畫庫
"react-native-communications": "^2.0.0", // 調用手機通訊功能
"react-native-image-picker": "^0.18.17", // 圖片選擇
"react-native-modalbox": "^1.3.3", // 模態框
"react-native-tab-navigator": "^0.2.18", // 導航欄
"react-native-viewpager": "^0.2.1", // 圖片輪播切換
"react-redux": "^4.4.5",
"redux": "^3.5.2",
"redux-thunk": "^2.0.1"
}
App裡錯誤提示和網站稍有不同,網站頁面寬度大,錯誤提示信息一般出現在輸入框的後面或者懸浮在右上角。但是在App裡,需要考慮用戶不同的屏幕尺寸,錯誤信息應該放在一個相對獨立且不影響其他元素顯示的位置,目前主流的展現形式是這樣的: 對外的API有以下幾個,顧名思義: 安裝和使用方法請查看 官方文檔 之前花時間研究過 下面是官方的Demo 在 這個組件安裝很簡單,支持的功能有:撥號、發短信、發Email、打開網頁 等 ,下面是官方一個綜合的例子: 調取手機相冊和上傳圖片是個老生常談的問題, 拎一段代碼片段: 模態框在App裡使用的也比較多,比如確認模態、加載模態、輸入模態等,出於良好的用戶體驗和兼容性考慮,我這裡底層采用 很常見,不多做介紹,copy下面代碼 直接可以使用 這個也很常見,copy下面代碼 直接可以使用 這個特別講解一下, 補充說明一下 這個組件其實 然後在container裡就可以使用了: 建議使用三方的 下面是一個demo:
即懸浮放置在頁面的中底部,並且定時自動關閉。這個玩意自己寫一個也不難,不過為了省事和好的兼容性,就直接使用三方的@remobile喎?/kf/ware/vc/" target="_blank" class="keylink">vcmVhY3QtbmF0aXZlLXRvYXN0PC9jb2RlPsHLoaPKudPDt723qMjnz8KjujwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
import Toast from '@remobile/react-native-toast';
// ...
Toast.showShortBottom('用戶名或密碼不正確');
Toast.showShortTop = function (message) {
showToast(message, "short", "top");
};
Toast.showShortCenter = function (message) {
showToast(message, "short", "center");
};
Toast.showShortBottom = function (message) {
showToast(message, "short", "bottom");
};
Toast.showLongTop = function (message) {
showToast(message, "long", "top");
};
Toast.showLongCenter = function (message) {
showToast(message, "long", "center");
};
Toast.showLongBottom = function (message) {
showToast(message, "long", "bottom");
};
Toast.show = function (message) {
showToast(message, "short", "bottom");
};
Toast.hide = function () {
RCTToast.hide();
};
動畫庫
CSS3
的動畫庫,其實目前主流的動畫類型和動畫創意就那麼些,感興趣的可以 clone一下 myAnimate 這個項目。一句話,CSS3
裡使用的動畫方案,ReactNative
裡也應有盡有。我這邊使用的是 react-native-animatable
組件。使用方式如下:
import * as Animatable from 'react-native-animatable';
class ExampleView extends Component {
render() {
return (
調用手機通訊功能
HybridApp
裡實現這個功能還是挺麻煩的,需要客戶端封裝好接口給H5調用,但是在ReactNative
裡,一個組件就能搞定—— react-native-communications
,安裝請查看官方文檔
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
import Communications from 'react-native-communications';
class RNCommunications extends Component({
render() {
return (
訪問手機相冊
ReactNative
裡可以通過react-native-image-picker
來處理,安裝請查看官方文檔
import ImagePicker from 'react-native-image-picker'
const options = {
title: '選擇上傳圖片', // specify null or empty string to remove the title
cancelButtonTitle: '取消',
takePhotoButtonTitle: '拍照...', // specify null or empty string to remove this button
chooseFromLibraryButtonTitle: '從庫中選擇...', // specify null or empty string to remove this button
//customButtons: {
// 'Choose Photo from Facebook': 'fb', // [Button Text] : [String returned upon selection]
//},
cameraType: 'back', // 'front' or 'back'
mediaType: 'photo',
//videoQuality: 'high', // 'low', 'medium', or 'high'
maxWidth: 200, // photos only
maxHeight: 200, // photos only
allowsEditing: true,
noData: false,
}
//...
onUpload() {
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
//console.log('User cancelled image picker');
}
else if (response.error) {
//console.log('ImagePicker Error: ', response.error);
} else {
let source = {uri: response.uri.replace('file://', ''), isLocal: true, isStatic: true};
this.setState({ form: {...this.state.form, avatar: source} })
}
})
}
模態框
react-native-modalbox
,然後根據不同功能進行二次加工。ConfirmModal
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import ModalBox from 'react-native-modalbox';
const styles = StyleSheet.create({
modal: {
borderRadius: 10,
},
modalContent: {
flex: 1,
paddingLeft: 10,
paddingRight: 10,
},
h2: {
marginTop: 15,
fontSize: 20,
color: '#555',
textAlign: 'center',
},
modalOption: {
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: '#ddd',
},
modalCancel: {
flex: 1,
padding: 15,
},
modalCancelText: {
fontSize: 16,
textAlign: 'center',
},
modalConfirm: {
flex: 1,
padding: 15,
borderLeftWidth: 1,
borderLeftColor: '#ddd',
},
modalConfirmText: {
fontSize: 16,
textAlign: 'center',
},
message: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
messageText: {
color: '#555',
fontSize: 16,
},
});
export default class ConfirmModal extends Component {
constructor(props) {
super(props);
}
open() {
this.refs.modal.open()
}
close() {
this.refs.modal.close()
}
render() {
let { width } = Dimensions.get('window');
return (
LoadingModal
import React, { Component } from 'react';
import {
StyleSheet,
} from 'react-native';
import ModalBox from 'react-native-modalbox';
const styles = StyleSheet.create({
modal: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'transparent'
},
});
export default class LoadingModal extends Component {
constructor(props) {
super(props);
}
open() {
this.refs.modal.open()
}
close() {
this.refs.modal.close()
}
render() {
return (
PickerModal
PickerModal
用於頁面上的Picker
的處理,顯示效果如下:
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableOpacity,
Picker,
View,
} from 'react-native';
import ModalBox from 'react-native-modalbox'
import dismissKeyboard from '../mixins/dismiss-keyboard'
const styles = StyleSheet.create({
popup: {
},
popupContent: {
flex: 1,
paddingLeft: 10,
paddingRight: 10,
},
h2: {
marginTop: 15,
fontSize: 20,
color: '#555',
textAlign: 'center',
},
popupOption: {
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: '#ddd',
},
popupCancel: {
flex: 1,
padding: 15,
},
popupCancelText: {
fontSize: 16,
textAlign: 'center',
},
popupConfirm: {
flex: 1,
padding: 15,
borderLeftWidth: 1,
borderLeftColor: '#ddd',
},
popupConfirmText: {
fontSize: 16,
textAlign: 'center',
},
message: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
messageText: {
color: '#555',
fontSize: 16,
},
});
export default class PickerModal extends Component {
constructor(props) {
super(props);
}
open() {
dismissKeyboard()
this.refs.modal.open()
}
close() {
this.refs.modal.close()
}
_renderPickerItems(data) {
data.map((item)=>{
return [
dismissKeyboard()
這個方法,該方法用於關閉頁面的keyboard
(鍵盤),ReactNative
默認沒有這種方法,需要自己編寫:
import { TextInput } from 'react-native';
const { State: TextInputState } = TextInput;
export default function dismissKeyboard() {
TextInputState.blurTextInput(TextInputState.currentlyFocusedField());
}
導航條
ReactNative
提供了原生版本的,但是樣式和功能上不好控制,建議自己手寫一個,代碼如下:
import React, { Component } from "react";
import {
Image,
Platform,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
const styles = StyleSheet.create({
leftButton: {
marginLeft: 5,
},
rightButton: {
marginRight: 5,
},
button: {
width: 44,
height: 44,
justifyContent: 'center',
alignItems: 'center',
},
nav: {
backgroundColor: '#f9f9f9',
flexDirection: 'row',
alignItems: 'center',
},
title: {
flex: 1,
height: 44,
justifyContent: 'center',
},
btnText: {
fontSize: 16,
color: '#777',
},
marginForIOS: {
marginTop: 20,
},
titleText: {
fontSize: 20,
textAlign: 'center',
color: '#555'
}
});
export class RightButton extends Component {
render() {
return (
import { NavigatorBar } from '../components/navigator'
// 沒有右側按鈕
圖片輪播
react-native-viewpager
組件,安裝請查看 官方文檔
var ViewPager = require('react-native-viewpager');
今天給大家講講有關自定義對話框的相關內容,前面兩篇都在在利用系統提供的函數來實現對話框,但局限性太大,當我們想自己定義視圖的時候,就不能利用系統函數了,就需要我們這裡的自
今天終於把老大交代的任務搞完了,感覺收獲挺多的,所以就寫一篇來記錄一下吧,首先還是來看一下,老大們的需求 需求: 希望移動端的用戶標識(IMEI)和HTML頁面的用戶
一、概述Drag拖拽;ViewDrag拖拽視圖,拖拽控件;ViewDragHelper拖拽視圖助手,拖拽操作類。利用ViewDragHelper類可以實現很多絢麗的效果,
對於大多數android開發者來說,ViewPager和ListView是再熟悉不過了,ViewPager的實現思路和ListView大同小異,具體參照前面的ListVi