How can I put an icon inside a TextInput in React Native?

JavascriptReact Native

Javascript Problem Overview


I am thinking of having something like this https://android-arsenal.com/details/1/3941 where you have icon that you press to show password as plaintext, not as dots. However, I was unable to find any custom component that would help me.

I don't want to put too much time on such a minor feature, so I'm asking without having attempted anything yet: Is there a custom component I've missed? If not, is there a simple way to add children to TextInput? Or should I just have TextInput and Touchable side by side?

Javascript Solutions


Solution 1 - Javascript

You can use combination of View, Icon and TextInput like so:

<View style={styles.searchSection}>
	<Icon style={styles.searchIcon} name="ios-search" size={20} color="#000"/>
	<TextInput
		style={styles.input}
		placeholder="User Nickname"
		onChangeText={(searchString) => {this.setState({searchString})}}
		underlineColorAndroid="transparent"
	/>
</View>

and use flex-direction for styling

searchSection: {
	flex: 1,
	flexDirection: 'row',
	justifyContent: 'center',
	alignItems: 'center',
	backgroundColor: '#fff',
},
searchIcon: {
	padding: 10,
},
input: {
	flex: 1,
	paddingTop: 10,
	paddingRight: 10,
	paddingBottom: 10,
	paddingLeft: 0,
	backgroundColor: '#fff',
	color: '#424242',
},

Icons were taken from "react-native-vector-icons"

Solution 2 - Javascript

Basically you can’t put an icon inside of a textInput but you can fake it by wrapping it inside a view and setting up some simple styling rules.

Here's how it works:

  • put both Icon and TextInput inside a parent View

  • set flexDirection of the parent to ‘row’ which will align the children next to each other

  • give TextInput flex 1 so it takes the full width of the parent View

  • give parent View a borderBottomWidth and push this border down with paddingBottom (this will make it appear like a regular textInput with a borderBottom)

  • (or you can add any other style depending on how you want it to look)

Code:

<View style={styles.passwordContainer}>
  <TextInput
    style={styles.inputStyle}
      autoCorrect={false}
      secureTextEntry
      placeholder="Password"
      value={this.state.password}
      onChangeText={this.onPasswordEntry}
    />
  <Icon
    name='what_ever_icon_you_want'
    color='#000'
    size={14}
  />
</View>

Style:

passwordContainer: {
  flexDirection: 'row',
  borderBottomWidth: 1,
  borderColor: '#000',
  paddingBottom: 10,
},
inputStyle: {
  flex: 1,
},

(Note: the icon is underneath the TextInput so it appears on the far right, if it was above TextInput it would appear on the left.)

Solution 3 - Javascript

This is working for me in ReactNative 0.60.4

View

<View style={styles.SectionStyle}>
    <Image
        source={require('../assets/images/ico-email.png')} //Change your icon image here
        style={styles.ImageStyle}
    />

    <TextInput
        style={{ flex: 1 }}
        placeholder="Enter Your Name Here"
        underlineColorAndroid="transparent"
    />
</View>

Styles

SectionStyle: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
    borderWidth: 0.5,
    borderColor: '#000',
    height: 40,
    borderRadius: 5,
    margin: 10,
},
ImageStyle: {
    padding: 10,
    margin: 5,
    height: 25,
    width: 25,
    resizeMode: 'stretch',
    alignItems: 'center',
}

Solution 4 - Javascript

In case is useful I share what I find a clean solution:

<View style={styles.inputContainer}>
  <TextInput
    style={styles.input}
    onChangeText={(text) => onChange(text)}
    value={value}
  />
  <Icon style={styles.icon} name="your-icon" size={20} />
</View>

and then in your css

 inputContainer: {
    justifyContent: 'center',
  },
  input: {
    height: 50,
  },
  icon: {
    position: 'absolute',
    right: 10,
  }

Solution 5 - Javascript

You can use this module which is easy to use: https://github.com/halilb/react-native-textinput-effects

Solution 6 - Javascript

You can wrap your TextInput in View.

and dynamically calculate width, if you want add an icon,

iconWidth = 0.05*viewWidth 
textInputWidth = 0.95*viewWidth

otherwise textInputwWidth = viewWidth.

View and TextInput background color are both white. (Small hack)

Solution 7 - Javascript

 import { TextInput } from 'react-native-paper';

 <TextInput
      label="Password"
      secureTextEntry
      right={<TextInput.Icon name="eye" />}
    />

Solution 8 - Javascript

//This is an example code to show Image Icon in TextInput// 
import React, { Component } from 'react';
//import react in our code.

import { StyleSheet, View, TextInput, Image } from 'react-native';
//import all the components we are going to use. 

export default class App extends Component<{}> {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.SectionStyle}>
          <Image
            //We are showing the Image from online
            source={{uri:'http://aboutreact.com/wp-content/uploads/2018/08/user.png',}}

            //You can also show the image from you project directory like below
            //source={require('./Images/user.png')}

            //Image Style
            style={styles.ImageStyle}
          />

          <TextInput
            style={{ flex: 1 }}
            placeholder="Enter Your Name Here"
            underlineColorAndroid="transparent"
          />
        </View>
         <View style={styles.SectionStyle}>
          <Image
            //We are showing the Image from online
            source={{uri:'http://aboutreact.com/wp-content/uploads/2018/08/phone.png',}}
            
            //You can also show the image from you project directory like below
            //source={require('./Images/phone.png')}

            //Image Style
            style={styles.ImageStyle}
          />

          <TextInput
            style={{ flex: 1 }}
            placeholder="Enter Your Mobile No Here"
            underlineColorAndroid="transparent"
          />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    margin: 10,
  },

  SectionStyle: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
    borderWidth: 0.5,
    borderColor: '#000',
    height: 40,
    borderRadius: 5,
    margin: 10,
  },

  ImageStyle: {
    padding: 10,
    margin: 5,
    height: 25,
    width: 25,
    resizeMode: 'stretch',
    alignItems: 'center',
  },
});

Expo

Solution 9 - Javascript

Anyone who's struggling on this

you can try to follow mine also

<View style={{flex:1}}>
     <KeyboardAvoidingView enabled>
     <View style={{flexDirection:'row',paddingBottom:5, borderColor:'#ccc',borderBottomWidth:1}}>
             <TextInput 
                  style={{flex:1}}
                  onChangeText={(UserEmail) => setUserEmail(userEmail)}
                  placeholder="Password"
                  placeholderTextColor="#ccc"
                  autoCapitalize="none"
                  keyboardType="default"
                  returnKeyType="next"
                  ref={passwordInputRef}
                  onSubmitEditing={Keyboard.dismiss}
                  blurOnSubmit={false}
                />
                <FontAwesome5 name={"eye"} size={25} style={{alignSelf:'center'}}/>
   </View>
   </KeyboardAvoidingView>
 </View>

Solution 10 - Javascript

Here you have an example I took from my own project, i have just removed what i thought we didnt need for the example.

import React, { Component } from 'react';
import {
  Text,
  TouchableOpacity,
  View,
  StyleSheet,
  Dimensions,
  Image
} from 'react-native';

class YourComponent extends Component {
  constructor(props) {
    super(props);

    this._makeYourEffectHere = this._makeYourEffectHere.bind(this);
	
	this.state = {
		showPassword: false,
		image: '../statics/showingPassImage.png'
	}
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity style={styles.button} onPress={this._makeYourEffectHere}>
          <Text>button</Text>
          <Image style={styles.image} source={require(this.state.image)}></Image>
        </TouchableOpacity>
		<TextInput password={this.state.showPassword} style={styles.input} value="abc" />
      </View>
    );
  }

  _makeYourEffectHere() {
	var png = this.state.showPassword ? '../statics/showingPassImage.png' : '../statics/hidingPassImage.png';
	this.setState({showPassword: !this.state.showPassword, image: png});
  }
}

var styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    justifyContent: 'center',
    flexDirection: 'column',
    alignItems: 'center',
  },
  button: {
    width: Dimensions.get('window').width * 0.94,
    height: 40,
    backgroundColor: '#3b5998',
    marginTop: Dimensions.get('window').width * 0.03,
    justifyContent: 'center',
    borderRadius: Dimensions.get('window').width * 0.012
  },
  image: {
    width: 25,
    height: 25,
    position: 'absolute',
    left: 7,
    bottom: 7
  },
  input: {
    width: Dimensions.get('window').width * 0.94,
    height: 30
  }
});

module.exports = YourComponent;

I hope It helps you.

Let me know if it was useful.

Solution 11 - Javascript

you can also do something more specific like that based on Anthony Artemiew's response:

<View style={globalStyles.searchSection}>
                    <TextInput
                        style={globalStyles.input}
                        placeholder="Rechercher"
                        onChangeText={(searchString) => 
                       {this.setState({searchString})}}
                        underlineColorAndroid="transparent"
                    />
                     <Ionicons onPress={()=>console.log('Recherche en cours...')} style={globalStyles.searchIcon} name="ios-search" size={30} color="#1764A5"/>

 </View>

Style:

 searchSection: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#fff',
        borderRadius:50,
        marginLeft:35,
        width:340,
        height:40,
        margin:25
    },
    searchIcon: {
        padding: 10,
    },
    input: {
        flex: 1,
        paddingTop: 10,
        paddingRight: 10,
        paddingBottom: 10,
        paddingLeft: 0,
        marginLeft:10,
        borderTopLeftRadius:50,
        borderBottomLeftRadius:50,
        backgroundColor: '#fff',
        color: '#424242',
    },

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZygroView Question on Stackoverflow
Solution 1 - JavascriptAnthony ArtemievView Answer on Stackoverflow
Solution 2 - JavascriptlinasmnewView Answer on Stackoverflow
Solution 3 - JavascriptGagandeep GambhirView Answer on Stackoverflow
Solution 4 - Javascriptc.chapaView Answer on Stackoverflow
Solution 5 - JavascriptLéoView Answer on Stackoverflow
Solution 6 - JavascriptSobol RomanView Answer on Stackoverflow
Solution 7 - JavascriptfidanView Answer on Stackoverflow
Solution 8 - JavascriptViraj SinghView Answer on Stackoverflow
Solution 9 - JavascriptGinxxxView Answer on Stackoverflow
Solution 10 - JavascriptFacundo La RoccaView Answer on Stackoverflow
Solution 11 - Javascriptguisszo 2.0View Answer on Stackoverflow