1. 日记本“新增”按钮

2. 创建日记本页面(未完成)
3. 试用react-native-datepicker,用于选择日记本过期时间
   - ios下月份显示英文,暂时没有配置项可以显示数字
   - 安卓下界面良好
This commit is contained in:
xuwenyang 2019-05-24 02:08:36 +08:00
parent 912cf0cabb
commit 0a7175a277
8 changed files with 333 additions and 1 deletions

View file

@ -5,4 +5,14 @@
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
</style> </style>
<style name="SpinnerDatePickerDialog" parent="android:Theme.Material.Light.Dialog">
<item name="android:datePickerStyle">@style/MyDatePicker</item>
<item name="android:colorAccent">#2196f3</item>
<item name="android:colorControlNormal">#2196f3</item>
</style>
<style name="MyDatePicker" parent="android:Widget.Material.DatePicker">
<item name="android:datePickerMode">spinner</item>
</style>
</resources> </resources>

8
package-lock.json generated
View file

@ -10821,6 +10821,14 @@
"resolved": "http://registry.npm.taobao.org/react-native-actionsheet-api/download/react-native-actionsheet-api-1.0.4.tgz", "resolved": "http://registry.npm.taobao.org/react-native-actionsheet-api/download/react-native-actionsheet-api-1.0.4.tgz",
"integrity": "sha1-AGJeOeRdy8KnERKB/xUDl+5ZUbI=" "integrity": "sha1-AGJeOeRdy8KnERKB/xUDl+5ZUbI="
}, },
"react-native-datepicker": {
"version": "1.7.2",
"resolved": "https://registry.npm.taobao.org/react-native-datepicker/download/react-native-datepicker-1.7.2.tgz",
"integrity": "sha1-WNCCJZGgrJsyq6CCZQIioO4pZp0=",
"requires": {
"moment": "^2.22.0"
}
},
"react-native-device-info": { "react-native-device-info": {
"version": "1.6.1", "version": "1.6.1",
"resolved": "https://registry.npm.taobao.org/react-native-device-info/download/react-native-device-info-1.6.1.tgz", "resolved": "https://registry.npm.taobao.org/react-native-device-info/download/react-native-device-info-1.6.1.tgz",

View file

@ -13,6 +13,7 @@
"react": "16.8.3", "react": "16.8.3",
"react-native": "0.59.5", "react-native": "0.59.5",
"react-native-actionsheet-api": "^1.0.4", "react-native-actionsheet-api": "^1.0.4",
"react-native-datepicker": "^1.7.2",
"react-native-device-info": "^1.6.1", "react-native-device-info": "^1.6.1",
"react-native-elements": "^0.19.0", "react-native-elements": "^0.19.0",
"react-native-iphone-x-helper": "^1.0.2", "react-native-iphone-x-helper": "^1.0.2",

View file

@ -0,0 +1,82 @@
import React, {Component} from 'react';
import {StyleSheet, Text, View, InteractionManager} from 'react-native';
import {Navigation} from 'react-native-navigation';
import DatePicker from 'react-native-datepicker'
function now() {
const d = new Date();
const localTime = d.getTime();
const localOffset = d.getTimezoneOffset() * 60000;
const utc = localTime + localOffset;
const offset = 8; //东 8 区
const beijingTime = utc + (3600000 * offset);
return new Date(beijingTime);
}
export default class DateInput extends Component {
constructor(props) {
super(props);
this.updateDate();
this.state = {
date: this.formatDate(this.nowDate)
};
}
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.updateDate();
});
}
updateDate() {
this.nowDate = now();
let nowMSec = this.nowDate.getTime();
let minExpiredMSec = 7 * 24 * 3600000; // at least 7 days to expire
let minExpiredDate = new Date(nowMSec + minExpiredMSec);
this.minDate = this.formatDate(minExpiredDate);
let maxExpiredMSec = 3650 * 24 * 3600000; // at most 10 years to expire
let maxExpireDate = new Date(nowMSec + maxExpiredMSec);
this.maxDate = this.formatDate(maxExpireDate);
}
formatDate(date) {
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
return year + '-' + month + '-' + day;
}
getDate() {
return this.state.date;
}
render() {
return (
<DatePicker mode="date" format="YYYY-MM-DD" showIcon={false}
style={this.props.style}
customStyles={this.props.customStyles}
confirmBtnText="确认"
cancelBtnText="取消"
placeholder="过期日期"
minDate={this.minDate}
maxDate={this.maxDate}
date={this.state.date}
onDateChange={(date) => {
this.setState({date: date})
}}
androidMode={'spinner'}
/>
);
}
}

View file

@ -0,0 +1,44 @@
import React, {Component} from 'react';
import {View, StyleSheet, Text, TouchableOpacity} from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import Color from '../../style/color'
export default class NotebookAdd extends Component {
_defaultOnPress() {
}
render() {
return (
<TouchableOpacity activeOpacity={0.7} onPress={
this.props.onPress ? this.props.onPress : this._defaultOnPress.bind(this)
}>
<View style={localStyle.box}>
<Ionicons name="md-add" size={48} color={Color.inactiveText} />
</View>
</TouchableOpacity>
);
}
}
const localStyle = StyleSheet.create({
box: {
flex: 1,
width: 140,
shadowColor: '#444',
shadowOpacity: 0.1,
shadowOffset: {
width: 0,
height: 0
},
elevation: 1,
backgroundColor: "#eee",
alignItems: 'center',
justifyContent: 'center',
margin: 3,
marginBottom: 15
}
});

View file

@ -12,6 +12,7 @@ import {Navigation} from 'react-native-navigation';
import Api from '../../util/api'; import Api from '../../util/api';
import Notebook from './notebook' import Notebook from './notebook'
import NotebookAdd from './notebookAdd'
export default class NotebookList extends Component { export default class NotebookList extends Component {
@ -59,6 +60,17 @@ export default class NotebookList extends Component {
return groups; return groups;
} }
_onAddPress() {
Navigation.push(this.props.componentId, {
component: {
name: 'NotebookAdd',
passProps: {
}
}
});
}
_onNotebookPress(notebook) { _onNotebookPress(notebook) {
Navigation.push(this.props.componentId, { Navigation.push(this.props.componentId, {
component: { component: {
@ -85,6 +97,10 @@ export default class NotebookList extends Component {
let user = this.state.user; let user = this.state.user;
(user ? Api.getUserNotebooks(user.id) : Api.getSelfNotebooks()) (user ? Api.getUserNotebooks(user.id) : Api.getSelfNotebooks())
.then(notebooks => { .then(notebooks => {
if(!user) {
notebooks.unshift({id: 'new'});
}
let groups = this.createGroup(notebooks, this.itemsPerRow); let groups = this.createGroup(notebooks, this.itemsPerRow);
this.setState({ this.setState({
notebooks: groups notebooks: groups
@ -95,6 +111,16 @@ export default class NotebookList extends Component {
}); });
} }
_renderAdd() {
return (<NotebookAdd key='new'
onPress={() => this._onAddPress()}>
</NotebookAdd>);
}
_renderPlaceHolder() {
return <View key="placeholder" style={{width: 140}} />;
}
_renderItem(notebook) { _renderItem(notebook) {
return notebook ? ( return notebook ? (
<TouchableOpacity key={notebook.id} activeOpacity={0.7} <TouchableOpacity key={notebook.id} activeOpacity={0.7}
@ -113,11 +139,18 @@ export default class NotebookList extends Component {
data={this.state.notebooks} data={this.state.notebooks}
keyExtractor={(item, index) => { keyExtractor={(item, index) => {
return item[0].id.toString() return item[0].id.toString();
}} }}
renderItem={({item}) => { renderItem={({item}) => {
let row = item.map((notebook) => { let row = item.map((notebook) => {
if(!notebook) {
return this._renderPlaceHolder();
} else if(notebook.id == 'new') {
return this._renderAdd();
}
return this._renderItem(notebook); return this._renderItem(notebook);
}); });

153
src/page/NotebookAddPage.js Normal file
View file

@ -0,0 +1,153 @@
import React, {Component} from 'react';
import {StyleSheet, Text, View, ScrollView, Switch, TextInput, TouchableOpacity} from 'react-native';
import {Navigation} from 'react-native-navigation';
import Color from '../style/color';
import {Icon} from '../style/icon';
import Api from '../util/api';
import DateInput from '../component/dateInput'
export default class NotebookAddPage extends Component {
constructor(props) {
super(props);
Navigation.events().bindComponent(this);
this.state = {
notebook: props.notebook,
subject: '',
isPublic: false,
dateString: ''
}
}
static options(passProps) {
return {
topBar: {
title: {
text: '创建日记本'
},
rightButtons: [{
id: 'save',
icon: Icon.navButtonSave
}]
},
bottomTabs: {
visible: false,
// hide bottom tab for android
drawBehind: true,
animate: true
}
};
}
navigationButtonPressed({buttonId}) {
console.log('date string:', this.dateInput.getDate());
}
render() {
return (
<View style={localStyle.wrap}>
<View style={localStyle.group}>
<View style={localStyle.item}>
<TextInput style={localStyle.subject}
underlineColorAndroid='transparent'
selectionColor={Color.primary}
autoCorrect={false}
placeholder="主题"
value={this.state.subject}
onChangeText={(text) => this.setState({subject: text})}
/>
</View>
<View style={localStyle.line} />
<View>
<View style={localStyle.item}>
<DateInput ref={(r) => {this.dateInput = r}}
style={localStyle.datePickerStyle}
customStyles={customDatePickerStyle}>
</DateInput>
</View>
</View>
<View style={localStyle.line} />
<View style={localStyle.item}>
<Text style={localStyle.title}>公开日记本</Text>
<Switch value={this.state.isPublic}
onValueChange={(v) => this.setState({isPublic: v})}
trackColor={Api.IS_ANDROID ? Color.textSelect : null}
thumbColor={Api.IS_ANDROID && this.state.isPublic ? Color.light : null}
/>
</View>
</View>
</View>
);
}
}
const localStyle = StyleSheet.create({
wrap: {
flex: 1,
backgroundColor: '#EFEFF4'
},
group: {
marginTop: 30,
backgroundColor: 'white',
borderTopWidth: StyleSheet.hairlineWidth,
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: '#c8c7cc'
},
item: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 15,
height: 45
},
subject: {
flex: 1,
fontSize: 16,
height: '100%',
padding: 0
},
title: {
fontSize: 16,
color: '#222'
},
line: {
marginLeft: 15,
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: '#c8c7cc'
},
datePickerStyle: {
flex: 1,
padding: 0,
height: '100%',
justifyContent: 'center'
}
});
const customDatePickerStyle = StyleSheet.create({
dateInput: {
height: 45,
alignItems: 'flex-start',
borderWidth: 0
},
placeholderText: {
fontSize: 16
},
dateText: {
fontSize: 16
}
});

View file

@ -3,6 +3,7 @@ DiaryDetail: require("./DiaryDetailPage.js").default,
Follow: require("./FollowPage.js").default, Follow: require("./FollowPage.js").default,
FollowUser: require("./FollowUserPage.js").default, FollowUser: require("./FollowUserPage.js").default,
Home: require("./HomePage.js").default, Home: require("./HomePage.js").default,
NotebookAdd: require("./NotebookAddPage.js").default,
NotebookDetail: require("./NotebookDetailPage.js").default, NotebookDetail: require("./NotebookDetailPage.js").default,
NotificationHistory: require("./NotificationHistoryPage.js").default, NotificationHistory: require("./NotificationHistoryPage.js").default,
Notification: require("./NotificationPage.js").default, Notification: require("./NotificationPage.js").default,