skip to Main Content

I’m building an OTP input component in React Native with four TextInput boxes, but I’m facing an issue where the cursor is not centered inside the box. Instead, it’s aligned to the right side of the box.

Here’s the relevant code I’m using:

<View style={styles.otpContainer}>
  {[...new Array(4)].map((_, index) => (
    <TextInput
      ref={ref => { inputs.current[index] = ref; }}
      style={[styles.otpInput, focusedIndex === index && { borderColor: tertiary }, emptyOtp && { borderColor: '#D00000' }, invalidOtp && { borderColor: '#D00000' }]}
      key={index}
      keyboardType="number-pad"
      maxLength={1}
      selectTextOnFocus
      contextMenuHidden
      testID={`OTPInput-${index}`}
      onChangeText={text => handleChangeText(text, index)}
      onKeyPress={e => handleKeyPress(e, index)}
      placeholder={focusedIndex !== index ? '•' : ''}
      onFocus={() => setFocusedIndex(index)} 
      onBlur={() => setFocusedIndex(-1)} 
    />
  ))}
</View>
otpContainer: {
  flexDirection: 'row',
  alignItems: 'center',
  justifyContent: 'center',
  gap: 8,
  marginTop: 40,
  textAlign: 'center',
},
otpInput: {
  borderWidth: 1,
  borderColor: '#ccc',
  borderRadius: 8,
  paddingHorizontal: 16,
  textAlign: 'center',
  fontSize: 24,
  color: '#000',
  lineHeight: 55,
  width: 55,
  height: 55,
}

The TextInput cursor seems to be slightly off-center, leaning towards the right side. I’ve already ensured that the textAlign: 'center' is set, but it still doesn’t work as expected.

Things I’ve tried:

  • Removing padding and adjusting lineHeight.
  • Ensuring width and height are consistent with fontSize.
  • Adjusting textAlign properties.

Has anyone faced this issue before or have any suggestions for fixing the cursor alignment?

2

Answers


  1. The paddingHorizontal property in your otpInput style may be causing the cursor to shift.
    React Native TextInput cursor alignment can also be influenced by fontSize, lineHeight, and any additional padding or margins.
    Try this:

    otpInput: {
      borderWidth: 1,
      borderColor: '#ccc',
      borderRadius: 8,
      textAlign: 'center',
      textAlignVertical: 'center', // Ensure vertical centering
      fontSize: 24,
      color: '#000',
      width: 55,
      height: 55,
      lineHeight: 55, // Match height
      padding: 0, // Avoid conflicting padding
    },
    Login or Signup to reply.
  2. You can try this code.

    import { Text, SafeAreaView, StyleSheet, View, TextInput } from 'react-native';
    import React, { useState, useRef } from 'react';
    
    export default function App() {
      const [focusedIndex, setFocusedIndex] = useState(-1);
      const inputs = useRef([]);
    
      const handleChangeText = (text, index) => {
        if (text && index < 3) {
          inputs.current[index + 1]?.focus();
        }
      };
    
      const handleKeyPress = (e, index) => {
        if (e.nativeEvent.key === 'Backspace' && index > 0) {
          inputs.current[index - 1]?.focus();
        }
      };
    
      return (
        <SafeAreaView style={styles.container}>
          <View style={styles.otpContainer}>
            {[...new Array(4)].map((_, index) => (
              <TextInput
                ref={(ref) => { inputs.current[index] = ref; }}
                style={[styles.otpInput, focusedIndex === index && { borderColor: 'blue' }]}
                key={index}
                keyboardType="number-pad"
                maxLength={1}
                selectTextOnFocus
                testID={`OTPInput-${index}`}
                onChangeText={(text) => handleChangeText(text, index)}
                onKeyPress={(e) => handleKeyPress(e, index)}
                placeholder={focusedIndex !== index ? '•' : ''}
                onFocus={() => setFocusedIndex(index)}
                onBlur={() => setFocusedIndex(-1)}
              />
            ))}
          </View>
        </SafeAreaView>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        backgroundColor: '#ecf0f1',
      },
      otpContainer: {
        flexDirection: 'row',
        justifyContent: 'center',
        textAlign: 'center',
        marginRight: 8,
      },
      otpInput: {
        borderWidth: 1,
        borderColor: '#ccc',
        borderRadius: 8,
        textAlign: 'center',
        fontSize: 24,
        color: '#000',
        width: 56,
        height: 55,
      },
    });
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search