Home > Blockchain >  Why closes my keyboard after every keystroke?
Why closes my keyboard after every keystroke?

Time:02-11

I'am working on an App for some algorithms. Something like "Question" if yes, then x and if no then y. Some I created a Component, for a single algorithm step.

Some of the answers are not only yes or no, so i added a optional text input to my component. If as possible answer in the algorithm "TextInput" there should be a TextInput Element and a Button with ok. After clicking Ok the TextInput should become a fixed Text. But after every keystroke the keyboard closes.

I found out, that this beahvior starts, after adding value and onTextChanged to the TextInput. But in other projects i got this exactly the same way working. Why? Can anyone help?

Here is my code for the component:

import { AutoSizeText, ResizeTextMode } from 'react-native-auto-size-text';
import { Dimensions, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { useState } from 'react';

export default function SingleAlgorithmStep(props) {
    const step = props.step;     //Inhalt des akutell auszuführenden Schritts
    const stepsDone = props.stepsDone;          //Array mit bereits erledigten Schritten
    const clickedButtons = props.clickedButtons;            //Array mit den bereits ausgewählten Buttons
    const currentAlgorithmJson = props.algorithmJson;           //Aktuellen Algorithmus von den Props auslesen

    const [textInputValue, changeTextInput] = useState('');

    let buttons = [];      //Array, was die Texte und die Anzahl der Buttons für diesen Step beinhaltet
    var buttonWidth = (Dimensions.get('window').width - 20);      //Breite eines Buttons entspricht der Bildschirmbreite abzüglich Rand
    if (Object.keys(step["Action"]).length > 1) {
        buttonWidth = (buttonWidth - (Object.keys(step["Action"]).length - 1) * 10) / Object.keys(step["Action"]).length;
    }     //Falls mehrere Buttons vorhanden sind, soll zwischen den Buttons etwas Platz sein und trotzdem sollen alle gleich groß sein

    for (const buttonText in step["Action"]) {
        const id = step["Question"]   " : "   buttonText;      //Einmalige ID erzeugen

        buttons = buttons.concat(
            <TouchableOpacity key={id} style={[styles.button, { width: buttonWidth, backgroundColor: clickedButtons.includes(id) ? "limegreen" : "dodgerblue" }]} onPress={() => {
                if (clickedButtons.filter(oldId => oldId.includes(step["Question"])).length > 0) {
                    //Falls auf einen bereits erledigten Schritt zurückgegangen wird...

                    props.actualizeButtons(clickedButtons.splice(0, stepsDone.indexOf(step)).concat(id));      //Gewählte Buttons werden bis zum Index des Schrittes beibehalten und der neue Button wird ergänzt
                    props.actualizeSteps(stepsDone.splice(0, stepsDone.indexOf(step)   1).concat(currentAlgorithmJson[step["Action"][buttonText]]));     //Schritte werden bis zum Index des aktuellen Steps beibehalten und der nächste Schritt ergänzt
                }
                else {
                    props.actualizeButtons(clickedButtons.concat(id));     //ID zum Array hinzufüge, um angeklickte Buttons zu markieren
                    props.actualizeSteps(stepsDone.concat(currentAlgorithmJson[step["Action"][buttonText]]));      //Nächsten Schritt einfügen
                }
            }}>
                <AutoSizeText style={[styles.buttonText, { width: buttonWidth }]} fontSize={18} minFontSize={18} numberOfLines={3} mode={ResizeTextMode.min_font_size}>{buttonText === "TextInput" ? "Ok" : buttonText}</AutoSizeText>
            </TouchableOpacity>
        );
    }     //Jeden Button aus dem JSON als Element zur Liste hinzufügen, um so dynamisch die Anzahl der Button und den Button Text zu regulieren

    return (
        <View style={{ marginBottom: 15 }}>
            <AutoSizeText style={styles.Question} fontSize={24} minFontSize={21} numberOfLines={5} mode={ResizeTextMode.min_font_size}>{step["Question"]}</AutoSizeText>
            {Object.keys(step["Action"]).includes("TextInput") ?  !clickedButtons.includes(step["Question"]   " : "   "TextInput") ? <TextInput key={Math.random()} style={styles.input} value={textInputValue} onChangeText={(textInputValue) => changeTextInput(textInputValue)} placeholder={step["Question"]}></TextInput> : <Text>{textInputValue}</Text> : null}
            <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
                {buttons}
            </View>
        </View>
    )
}

const styles = StyleSheet.create({
    Question: {
        width: Dimensions.get('window').width - 20,
        minHeight: 40,
        borderColor: 'black',
        borderWidth: 2,
        textAlign: 'center',
    },
    input: {
        borderWidth: 1,
        borderColor: 'black',
        width: '100%',
        fontSize: 18,
        padding: 5,
        marginTop: 5,
    },
    button: {
        marginTop: 10,
        minHeight: 30,
        justifyContent: 'space-around'
    },
    buttonText: {
        textAlign: 'center',
        color: 'white',
        minHeight: 30,
        textAlignVertical: 'center'
    }
});

CodePudding user response:

This is the default behavior when TextInput is a child component to scrollable components, ScrollView, FlatList OR SectionList.

Make always keyboard persist tap as below:

<FlatList
keyboardShouldPersistTaps="always"

//...otherProps
 />

Then remove the key prop which is set to Math.random(). The random number value is dynamic for each rerender and doesn't provide any performance benefit.

<TextInput
  //key={Math.random()}  - Key should not be random number
  style={styles.input}
  value={textInputValue}
  onChangeText={(textInputValue) => changeTextInput(textInputValue)}
  placeholder={step["Question"]}
/>;


Here working snack - https://snack.expo.dev/@emmbyiringiro/1920d6

  • Related