Skip to content

Instantly share code, notes, and snippets.

@mosluce
Last active July 30, 2018 15:08
Show Gist options
  • Save mosluce/ddef03746c585cb025269da728e3d615 to your computer and use it in GitHub Desktop.
Save mosluce/ddef03746c585cb025269da728e3d615 to your computer and use it in GitHub Desktop.
import React, { PureComponent } from "react";
import {
View,
TextInput,
TextInputProps,
ViewStyle,
TextStyle,
StyleProp,
Platform,
} from "react-native";
import {
} from "react-native-material-ui";
import PropTypes from 'prop-types';
export type InputProps = TextInputProps & {
style: {
container: StyleProp<ViewStyle>,
inputContainer: StyleProp<View>,
input: StyleProp<TextStyle>,
},
centerElement: JSX.Element,
leftElement: JSX.Element,
rightElement: JSX.Element,
highlightColor: string,
disabledColor: string,
normalColor: string,
errorColor: string,
underLineWidth: number,
}
const defaultStyle = {
inputContainer: {
paddingTop: 8,
paddingBottom: 8,
marginLeft: 16,
marginRight: 16,
},
input: {
fontFamily: 'Roboto',
fontSize: 16,
color: 'rgba(0, 0, 0, 0.87)',
}
};
class Input extends PureComponent<InputProps> {
constructor() {
super();
this.state = {
focus: false
};
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
onFocus(e) {
this.setState({
focus: true,
})
this.props.onFocus && this.props.onFocus(e);
}
onBlur(e) {
this.setState({
focus: false,
})
this.props.onBlur && this.props.onBlur(e);
}
render() {
const {
style,
leftElement,
rightElement,
placeholder,
placeholderTextColor,
normalColor,
highlightColor,
editable,
disabledColor,
text,
underLineWidth,
centerElement,
} = this.props;
const inputStyle = [defaultStyle.input, style.input];
if (!editable) inputStyle.push({ color: disabledColor });
const FormGroup = Platform.select({
ios: ({ children }) => (
<View style={[
defaultStyle.inputContainer,
style.inputContainer,
{ flex: 1, flexDirection: 'row', flexWrap: 'wrap' }
]}>
{children}
</View>
),
android: ({ children }) => (
<View style={[
defaultStyle.inputContainer,
style.inputContainer,
{ flex: 1, marginBottom: -12, marginTop: -4, flexDirection: 'row', flexWrap: 'wrap' }
]}>{children}</View>
)
})
const { children, ...textProps } = this.props;
return (
<View>
<View style={[style.container, { flexDirection: 'row', alignItems: 'flex-end', flexWrap: 'wrap' }]}>
{leftElement}
<FormGroup>
{children}
{centerElement || (
<TextInput
{...textProps}
defaultValue={text}
style={inputStyle}
onFocus={this.onFocus}
onBlur={this.onBlur}
/>
)}
</FormGroup>
{rightElement}
</View>
<View style={{
backgroundColor: !editable ? disabledColor : this.state.focus ? highlightColor : normalColor,
height: underLineWidth,
}} />
</View>
)
}
}
export const InputSample = () => {
return (
<View style={{ marginHorizontal: 16 }}>
<View style={{ marginBottom: 8 }}>
<Input placeholder="輸入文字" />
</View>
<View style={{ marginBottom: 8 }}>
<Input value="已輸入文字(變更文字樣式)" style={{ input: { color: 'green' } }} >
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
<View style={{ backgroundColor: '#ccc', margin: 4, width: 50, height: 30 }} />
</Input>
</View>
<View style={{ marginBottom: 8 }}>
<Input value="已輸入文字(readonly)" editable={false} disabledColor="#ccc" />
</View>
<View style={{ marginBottom: 8 }}>
<Input
value="左右Elemet"
leftElement={<View style={{ width: 100, height: 50, backgroundColor: '#ccc' }} />}
rightElement={<View style={{ width: 100, height: 50, backgroundColor: '#222' }} />} />
</View>
</View>
)
}
Input.defaultProps = {
placeholderTextColor: 'rgba(0, 0, 0, 0.38)',
normalColor: 'rgba(0, 0, 0, 0.54)',
highlightColor: 'rgba(0, 0, 0, 0.54)',
disabledColor: 'rgba(0, 0, 0, 0.54)',
underLineWidth: 2,
style: defaultStyle,
editable: true,
};
export default Input;
import React, { PureComponent } from "react";
import {
View,
Text,
ViewStyle,
TextStyle,
StyleProp,
Platform,
PickerItemProps,
Animated,
Modal,
PickerIOS,
DatePickerIOS
} from "react-native";
import {
} from "react-native-material-ui";
import PropTypes from 'prop-types';
import Input, { InputProps } from "./Input";
import TouchableView from './TouchableView';
export type SelectProps = InputProps & {
options: Array<PickerItemProps>,
value: any,
}
const defaultStyle = Input.defaultProps.style;
class Select extends PureComponent<SelectProps> {
constructor(props) {
super(props);
this.state = {
value: this.props.value,
selectedValue: this.props.value,
modalVisible: false,
animatedHeight: new Animated.Value(0),
};
this.setModalVisible = this.setModalVisible.bind(this);
this.onMaskPress = this.onMaskPress.bind(this);
this.onPickerPress = this.onPickerPress.bind(this);
this.onValueChange = this.onValueChange.bind(this);
}
/// iOS only start
setModalVisible(visible) {
if (visible) {
this.setState({
modalVisible: true,
});
Animated.timing(
this.state.animatedHeight,
{
toValue: 275,
duration: 250
}
).start();
} else {
Animated.timing(
this.state.animatedHeight,
{
toValue: 0,
duration: 250
}
).start(() => this.setState({ modalVisible: false }));
}
}
onPickerPress() {
this.setModalVisible(true);
}
onMaskPress() {
this.setModalVisible(false);
}
/// iOS only end
onValueChange(value) {
this.setState({
value: value,
});
}
renderSelect() {
const { style, options } = this.props;
const { value, animatedHeight, modalVisible } = this.state;
console.log(this.state);
let displayText = '';
if (options.length > 0 && value !== undefined) {
const option = options.filter(o => o.value == value)[0];
option && (displayText = option.label);
}
return (
<TouchableView style={{ flex: 1 }} onPress={() => this.onPickerPress()}>
<Text style={[defaultStyle.input, style.input]}>
{displayText}
</Text>
<Modal
transparent={true}
animationType="none"
visible={this.state.modalVisible}
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => {
this.setModalVisible(false);
}}>
<View style={{ flex: 1 }}>
<TouchableView
style={{
flex: 1,
alignItems: 'flex-end',
flexDirection: 'row',
backgroundColor: '#00000077'
}}
onPress={() => this.onMaskPress()}>
<TouchableView
style={{
flex: 1,
}}>
<Animated.View style={{ height: animatedHeight, backgroundColor: '#fff', }}>
<View>
<PickerIOS
style={{
marginTop: 42
}}
onValueChange={this.onValueChange}>
{options.map((option, i) => <PickerIOS.Item key={i} {...option} />)}
</PickerIOS>
{/*
<DatePickerIOS
date={new Date()}
onDateChange={(date) => this.onValueChange(date)}
/>
*/}
</View>
</Animated.View>
</TouchableView>
</TouchableView>
</View>
</Modal>
</TouchableView >
)
}
render() {
return (
<Input
{...this.props}
centerElement={this.renderSelect()}
/>
)
}
}
Select.defaultProps = {
style: defaultStyle,
options: [{
label: "X",
value: 0,
}, {
label: "Y",
value: 1,
}, {
label: "Z",
value: 2,
}],
value: 0,
}
export default Select;
import React, { PureComponent } from "react";
import {
View,
TouchableWithoutFeedback,
ViewProps,
TouchableWithoutFeedbackProps,
} from "react-native";
import {
} from "react-native-material-ui";
import PropTypes from 'prop-types';
class TouchableView extends PureComponent<ViewProps & TouchableWithoutFeedbackProps> {
render() {
return (
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View {...this.props}>{this.props.children}</View>
</TouchableWithoutFeedback>
)
}
}
export default TouchableView;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment