Skip to content

Instantly share code, notes, and snippets.

@pstockley
Created October 6, 2016 01:48
Show Gist options
  • Save pstockley/f61623412aacca89ca8d8cc831d3cec2 to your computer and use it in GitHub Desktop.
Save pstockley/f61623412aacca89ca8d8cc831d3cec2 to your computer and use it in GitHub Desktop.
Cross Platform Search Field on Exponent
/* @flow */
import React from 'react';
import {StyleSheet, Text, View, TextInput, Platform} from 'react-native';
import _ from 'lodash';
import {MaterialIcons, Ionicons} from '@exponent/vector-icons';
import TouchableNativeFeedbackSafe from '@exponent/react-native-touchable-native-feedback-safe/TouchableNativeFeedbackSafe';
type KeyBoardType = "default" | "email-address" | "numeric" | "phone-pad" |
//ios only
"ascii-capable" | "numbers-and-punctuation" | "url" | "number-pad" |
"name-phone-pad" | "decimal-pad" | "twitter" | "web-search";
type AutoCapitalizeMode = 'none' | 'sentences' | 'words' | 'characters';
export default class SearchField extends React.Component {
props: {
textColor: string,
iconColor: string,
style: any,
placeholder: string,
maxLength: number,
keyboardType: KeyBoardType,
autoCapitalize : AutoCapitalizeMode,
autoCorrect: boolean,
selectTextOnFocus: boolean,
defaultValue: string,
onChangeText: (newValue: string) => void
};
state: {searchValue: string} = {searchValue: ""};
render() {
const textInputProps = _.omit(this.props, "style", "textColor");
return (
<View style={[this.props.style, styles.searchCont]}>
<View style={styles.icon}>
{ RenderPlatformSpecificIcon("search", "ios-search", 16, this.props.iconColor) }
</View>
<TextInput
{ ...textInputProps }
placeholderTextColor={this.props.textColor}
returnKeyType="search"
style={ [styles.inputBox, {color: this.props.textColor}] }
value={ this.state.searchValue }
onChangeText={ this._onChangeText }
underlineColorAndroid="rgba(255,255,255,1.0)"/>
{ this._renderClearIndicator(this.state.searchValue) }
</View>
)
}
_onChangeText = (newValue: string) => {
this.setState({searchValue: newValue});
this.props.onChangeText(newValue);
};
_renderClearIndicator(searchValue: string) {
if (searchValue.length === 0)
return null;
else
return <PlatformSpecificIconButton
color={this.props.iconColor}
iconName="do-not-disturb-on"
iosIconName="md-close-circle"
size={16}
onPress={this._onClearText}
style={styles.icon}/>;
}
_onClearText = () => {
this.setState({searchValue: ""});
this.props.onChangeText("");
};
}
type PlatformSpecificIconButtonProps = {
onPress: Function,
iosIconName?: string, //The Ion Icon to display on ios
iconName: string, //The Material Icon to display by default or if on andriod
size: number,
color: string,
style?: any
}
export function PlatformSpecificIconButton(props: PlatformSpecificIconButtonProps) {
return (
<TouchableNativeFeedbackSafe onPress={props.onPress} style={props.style}>
{ RenderPlatformSpecificIcon(props.iconName, props.iosIconName, props.size, props.color) }
</TouchableNativeFeedbackSafe>
)
}
function RenderPlatformSpecificIcon(iconName: string, iosIconName: ?string, size: number, color: string) {
if (iosIconName && Platform.OS === 'ios') {
return (
<Ionicons
name={iosIconName}
size={size}
color={color}/>
)
} else {
return (
<MaterialIcons
name={iconName}
size={size}
color={color}/>
)
}
}
const styles = StyleSheet.create({
searchCont: {
borderRadius: (Platform.OS === 'ios') ? 5 : 0,
backgroundColor: "#FFF",
paddingHorizontal: 5,
paddingVertical: 3,
flex: 0,
flexDirection: 'row',
alignItems: 'center'
},
inputBox: {
flex: 1,
marginLeft: 3,
fontSize: 14
},
icon: {
flex: 0
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment