Робота з клавіатурою

Під час роботи на мобільних пристроях (особливо це стосується iOS) можуть виникнути такі проблеми у поведінці клавіатури:

  • Клавіатура перекриває інпут і не видно введений текст.

  • Клавіатура не закривається при кліку поза її областю після завершення введення тексту.

Проемулюйте цей код на iOS та на Android (при інпуті у фокусі він перекривається клавіатурою і клавіатура не прибирається при натисканні на вільне поле). Або скопіюйте цей код собі в редактор.

Резервний код
App.js
import React, { useState } from "react";
import {
  StyleSheet,
  View,
  TextInput,
} from "react-native";

export default function App() {
  const [text, setText] = useState("");
  return (
      <View style={styles.container}>
        <TextInput
          placeholder="Type text"
          value={text}
          onChangeText={setText}
          style={styles.input}
        />
      </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "flex-end",
    paddingBottom: 30
  },
  input: {
     width: 250,
    padding: 15,

    borderWidth: 1,
    borderColor: "blue",
    borderRadius: 10,
  },
});

Виправлення перекриття

Щоб розв'язати проблему перекриття інпуту клавіатурою потрібно використати компонент KeyboardAvoidingView. А саме - в нього огорнути наш TextInput.

Компонент KeyboardAvoidingView має проп behavior, який для iOS повинен бути padding і для Android повинен бути height.

Для визначення операційної системи використовують компонент Platform із ключем OS пристрою на якому відкрилася програма.

<KeyboardAvoidingView behavior={Platform.OS == "ios" ? "padding" : "height"}>

</KeyboardAvoidingView>
Резервний код
App.js
import React, { useState } from "react";
import {
  StyleSheet,
  View,
  TextInput,
  KeyboardAvoidingView, // new import
  Platform, // new import
} from "react-native";

export default function App() {
  const [text, setText] = useState("");
  return (
      <View style={styles.container}>
        <KeyboardAvoidingView 
        behavior={Platform.OS == "ios" ? "padding" : "height"}
        >
          <TextInput
          placeholder="Type text"
          value={text}
          onChangeText={setText}
          style={styles.input}
        />
        </KeyboardAvoidingView>
      </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "flex-end",
    paddingBottom: 30
  },
  input: {
     width: 250,
    padding: 15,

    borderWidth: 1,
    borderColor: "blue",
    borderRadius: 10,
  },
});

Виправлення закриття клавіатури

Все ще лишається проблема, що при натиску в будь-якому місці інтерфейсу поза інпутом клавіатура не зникає. Щоб це виправити потрібно скористатися компонентом TouchableWithoutFeedback. Цей компонент реагує на доторк до екрану. Він виступає обгорткою. У нього потрібно помістити увесь контейнер, щоб під час кліку в будь-якому місці контейнера клавіатура зникала. При цьому на подію onPress потрібно передати метод клавіатури dismiss.

<TouchableWithoutFeedback onPress={Keyboard.dismiss}>

</TouchableWithoutFeedback>
Резервний код
App.js
import React, { useState } from "react";
import {
  StyleSheet,
  View,
  TextInput,
  KeyboardAvoidingView, 
  Platform, 
  TouchableWithoutFeedback, // new import
  Keyboard, // new import
} from "react-native";

export default function App() {
  const [text, setText] = useState("");
  return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
     <View style={styles.container}>
        <KeyboardAvoidingView 
        behavior={Platform.OS == "ios" ? "padding" : "height"}
        >
          <TextInput
          placeholder="Type text"
          value={text}
          onChangeText={setText}
          style={styles.input}
        />
        </KeyboardAvoidingView>
      </View>
</TouchableWithoutFeedback>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "flex-end",
    paddingBottom: 30
  },
  input: {
     width: 250,
    padding: 15,

    borderWidth: 1,
    borderColor: "blue",
    borderRadius: 10,
  },
});

На Android навіть без додавання KeyboardAvoidingView клавіатура не перекриває інпут (навіть якщо він внизу сторінки).

На Android при фокусі інпута весь ваш екран зсувається вгору при появі клавіатури. Це відбувається, бо всередині Android є спеціальне налаштування для поведінки клавіатури і за замовченням проєкт має таке значення, що клавіатура поводить себе не так, як у iOS.

Аби зробити поведінку однаковою на обох платформах і керувати переркриттям клавіатури за допомогою KeyboarAvoidingView як в iOS так і на Android треба змінити налаштування андроід у файлі app.json, а саме: { "android": { "softwareKeyboardLayoutMode": "pan" } }

Документація цієї властивості тут. Документація, як додавати властивості у Expo - тут. Розширення у VSCode, яке буде підсвічувати доступні властивості, їх можливі значення і що вони роблять.

Посилання на документацію:

softwarekeyboardlayoutmode

Last updated