1. 程式人生 > >React Native Keyboard Covering Inputs

React Native Keyboard Covering Inputs

React Native Keyboard Covering Inputs

Exploring solutions for handling the keyboard covering inputs in React Native applications.

The final example in this article is available for download.

Prerequisites

In order to follow along, one will need to install:

  • Node.js LTS; currently 8.12.0
  • Yarn; create-react-native-app
    is not compatible with npm > 4 (ships with the latest version of Node.js LTS)

The Problem

Let us say we have a user interface that consists of text inputs that are evenly distributed vertically over the entire height of the screen. One reasonable implementation of this is to use an absolutely positioned view (whole screen) using flexbox to distribute the text inputs.

App.js

When using this implementation, typing into the B text input behaves as expected; the on-screen keyboard appears and one can see the text being entered. However, when typing into the D text input the keyboard covers it.

The general problem is that React Native does not automatically account for the on-screen keyboard covering up a portion of the screen.

note: While Android devices do have some provisions to handle this situation, i.e., android:windowSoftInputMode in the AndroidManifest.xml, we are looking for a cross-platform (Android and IOS) solution.

The Failures

The first example, KeyboardAvoidingView component looked very promising:

  • It is a built-in React Native component
  • Its usage is fairly simple; just a couple of properties

The problem with it, however, was:

  • The official documentation is virtually non-existent; with no examples given
  • The existing documentation is vague, e.g., “Android and iOS both interact with this prop differently. Android may behave better when given no behavior prop at all, whereas iOS is the opposite.
  • Never was able to get it to properly interact with an absolutely positioned view

As for the second example in the article, was not overly excited to use a third-party library: react-native-keyboard-aware-scroll-view; but at this point we are looking for a solution.

The libraries’ default usage is to replace one of the scrolling views ScrollView, ListView, SectionList and FlatList (none are the case that we are interested in).

The documentation on react-native-keyboard-aware-scroll-view, does suggest that the library can be used with other components using the provided KeyboardAwareHOC higher order component. The documentation, however, was weak; with no real example provided.

note: Also, react-native-keyboard-aware-scroll-view does not support Android without special considerations.

The Solution

The third example in the article, Keyboard, is promising:

  • It is a built-in React Native component
  • Its usage is fairly simple; just a couple of methods
  • It provides fairly low-level access; thus can be used in many different ways
  • Most importantly, we can use this approach in a fairly straightforward way to solve the problem

When using this implementation, as before, typing into the B text input behaves as expected; the on-screen keyboard appears and one can see the text being entered.

This time, however, typing into the D text input causes the screen to animate upwards so that the text input is just visible above the keyboard. Likewise, exiting the text input causes the screen to animate downwards so that the text input is returned to its original position.

note: The animation is an important touch; emphasizes what is going on.

Let us look at the updated code:

App.js

Observations:

  • The first observation is that the layout (render) and styling (styles) are left virtually untouched from our original example; changed the outermost component to an Animated.View and added a transform / translateY style
  • Used transform / translateY styling for Animated, instead of setting the top (in absolute positioning) for performance reasons. This is something that is well understood in web development and carries over to React Native.
  • We use Keyboard to listen for the keyboard showing and hiding; and the keyboard height
  • We use the undocumented (?) React Native method, TextInput.State.currentlyFocusedField, to determine the currently focused field (and thus its position on the screen).

An Abstraction using Render Props

Thinking about our solution, we certainly do not want to repeat the code related to shifting the content due to the keyboard in multiple components; i.e., we want to abstract that functionality into reusable code.

One solution is to create a component that follows the render prop pattern and use it to wrap specific components that require this functionality; for example here is our original code wrapped in a KeyboardShift component:

App.js

with:

KeyboardShift.js

Observations:

  • This is essentially the previous solution with the rendering specifics being supplied by a render prop (children)
  • Added the prop-types package to the project for PropTypes
  • The use of render props (as opposed to just supplying children) is a bit of an overkill; used it as it is a well-documented and extensible approach

Wrap Up

Hope you found this useful.