Всем привет! Сегодня делимся с вами познавательным материалом, перевод которого подготовлен специально для студентов курса «ReactJS/React Native-разработчик».

Итак, начнем.
Все мы видели такие поля для ввода:

Надпись большая и выглядит как плейсхолдер, пока вы не наведете фокус на ввод. Она станет меньше и поднимется вверх.
Выглядит великолепно. Гладко. Безупречно.
А еще кажется, что только опытный разработчик может так сделать, не правда ли?
Ну, возможно, это и было так до появления React Native, в те времена, когда люди жили в пещерах и творили всякую дичь. Но это осталось в прошлом.
Вы можете посмотреть видео или продолжить читать. Все зависит от того, что вам больше по душе.
Есть два варианта того, с чем мы имеем дело.
Первый – когда на поле ввода нет фокуса.

Надпись появляется внутри поля ввода, а ее размер равен размеру текстового поля. Цвет тусклый. Это очень похоже на свойство
И второй вариант, когда на поле ввода есть фокус.

Надпись оказывается над полем ввода, ее размер меньше, и цвет отличается от цвета вводимого текста.
Наконец-то мы можем приступить к работе. Пока без каких-либо анимаций.
Как оказалось, у нас есть два состояния UI:

По факту, мы могли бы хранить состояние того, есть фокус на поле или нет. Затем в зависимости от этого состояния, мы могли бы выбрать, где размещать надпись и какие стили к ней применить.
Поскольку надпись должна находиться в разных местах, и мы не хотим, чтобы она влияла на размещение компонентов, мы будем позиционировать ее абсолютно. Чтобы убедиться, что места для нее хватит, придется добавить в wrapping view отступ сверху.
После предыдущих шагов, мы можем достичь следующего:
https://snack.expo.io/Sk006AbdW?session_id=snack-session-JRMksbYK3
И это хорошая отправная точка. Пока у нас нет анимаций, но мы уже можем изменить местоположение надписи в зависимости от того, где находится фокус.
На самом деле осталась самая легкая часть.
Поскольку у нас есть два состояния, в которых может быть надпись, и мы выбираем одно, в зависимости от фокуса, а сама анимация этого перехода между состояниями довольно тривиальна.
Из этого руководства мы можем выделить следующее:
Реализовать это все несложно.
Затем, поскольку значение этого числа должно основываться на том, есть ли фокус на поле ввода или нет, и поскольку у нас уже есть этот бит информации о состоянии, мы можем добавить функцию
Теперь, чтобы отразить стиль надписи в таких терминах, нам понадобится внести всего два изменения:
Меняем на
Вместо того, чтобы использовать условия для определения стилей, определяйте их следующим образом:
https://snack.expo.io/Hk8VCR-dZ?session_id=snack-session-AJ4vulSVw
Если в демо выше вы попробуете что-нибудь ввести, а затем убрать фокус с поля ввода, то увидите нечто странное.

К счастью, это довольно просто исправить. Нам нужно всего лишь поменять две строчки в коде.
Мы хотим проверить, пустое ли поле ввода и изменить состояние на “unfocused”, только если оба следующих условия выполняются:
В противном случае, мы хотим, чтобы применялся стиль “focused”, а замещающая надпись поднималась вверх.
Теперь, когда мы отслеживаем состояние поля ввода, мы можем легко получить доступ к его значению с помощью

https://snack.expo.io/ByZBAC-dZ?session_id=snack-session-YNZSqhqOC
На этом всё. До встречи на бесплатном вебинаре.

Итак, начнем.
Все мы видели такие поля для ввода:

Надпись большая и выглядит как плейсхолдер, пока вы не наведете фокус на ввод. Она станет меньше и поднимется вверх.
Выглядит великолепно. Гладко. Безупречно.
А еще кажется, что только опытный разработчик может так сделать, не правда ли?
Ну, возможно, это и было так до появления React Native, в те времена, когда люди жили в пещерах и творили всякую дичь. Но это осталось в прошлом.
Вы можете посмотреть видео или продолжить читать. Все зависит от того, что вам больше по душе.
Чего мы добиваемся?
Есть два варианта того, с чем мы имеем дело.
Первый – когда на поле ввода нет фокуса.

Надпись появляется внутри поля ввода, а ее размер равен размеру текстового поля. Цвет тусклый. Это очень похоже на свойство
placeholder.И второй вариант, когда на поле ввода есть фокус.

Надпись оказывается над полем ввода, ее размер меньше, и цвет отличается от цвета вводимого текста.
Простейшая реализация
Наконец-то мы можем приступить к работе. Пока без каких-либо анимаций.
Как оказалось, у нас есть два состояния UI:
- На поле нет фокуса и надпись внутри поля.
- На поле есть фокус, надпись над полем ввода.

По факту, мы могли бы хранить состояние того, есть фокус на поле или нет. Затем в зависимости от этого состояния, мы могли бы выбрать, где размещать надпись и какие стили к ней применить.
Поскольку надпись должна находиться в разных местах, и мы не хотим, чтобы она влияла на размещение компонентов, мы будем позиционировать ее абсолютно. Чтобы убедиться, что места для нее хватит, придется добавить в wrapping view отступ сверху.
class FloatingLabelInput extends Component { state = { isFocused: false, }; handleFocus = () => this.setState({ isFocused: true }); handleBlur = () => this.setState({ isFocused: false }); render() { const { label, ...props } = this.props; const { isFocused } = this.state; const labelStyle = { position: 'absolute', left: 0, top: !isFocused ? 18 : 0, fontSize: !isFocused ? 20 : 14, color: !isFocused ? '#aaa' : '#000', }; return ( <View style={{ paddingTop: 18 }}> <Text style={labelStyle}> {label} </Text> <TextInput {...props} style={{ height: 26, fontSize: 20, color: '#000', borderBottomWidth: 1, borderBottomColor: '#555' }} onFocus={this.handleFocus} onBlur={this.handleBlur} /> </View> ); } }
<FloatingLabelInput label="Email" value={this.state.value} onChange={this.handleTextChange} />
После предыдущих шагов, мы можем достичь следующего:
https://snack.expo.io/Sk006AbdW?session_id=snack-session-JRMksbYK3
И это хорошая отправная точка. Пока у нас нет анимаций, но мы уже можем изменить местоположение надписи в зависимости от того, где находится фокус.
Почему бы не использовать
placeholder?
Конечно, использование свойстваTextInputплейсхолдера кажется заманчивым. Однако это не сработает, поскольку мы хотим контролировать как, когда и где отображается надпись.
Вместо этого, мы хотим, чтобы надпись находилась внутри текстового поля, когда на нем фокус. А еще мы хотим, чтобы она сдвигалась вверх, когда на поле ввода появляется фокус, и этого можно достичь только, если мы работаем с одним и тем же элементом.
Как насчет анимации?
На самом деле осталась самая легкая часть.
Поскольку у нас есть два состояния, в которых может быть надпись, и мы выбираем одно, в зависимости от фокуса, а сама анимация этого перехода между состояниями довольно тривиальна.
Из этого руководства мы можем выделить следующее:
Animated.Valueбудет означать, есть фокус на поле (1) или нет (0);- Мы постепенно будем менять число на (1) при фокусировке и на (0) в противном случае;
- В виде этого числа мы будем отражать стиль надписи: в (0) и (1) мы определим стили, а React Native автоматически вычислит и применит промежуточные стили. И даже цвета.
Реализовать это все несложно.
Animated.Value нам нужно будет инициализировать в componentWillMount.componentWillMount() { this._animatedIsFocused = new Animated.Value(0); }
Затем, поскольку значение этого числа должно основываться на том, есть ли фокус на поле ввода или нет, и поскольку у нас уже есть этот бит информации о состоянии, мы можем добавить функцию
componentDidUpdate, которая будет менять это число в зависимости от this.state: componentDidUpdate() { Animated.timing(this._animatedIsFocused, { toValue: this.state.isFocused ? 1 : 0, duration: 200, }).start(); }
Теперь, чтобы отразить стиль надписи в таких терминах, нам понадобится внести всего два изменения:
Меняем на
Animated.Text.Вместо того, чтобы использовать условия для определения стилей, определяйте их следующим образом:
const labelStyle = { position: 'absolute', left: 0, top: this._animatedIsFocused.interpolate({ inputRange: [0, 1], outputRange: [18, 0], }), fontSize: this._animatedIsFocused.interpolate({ inputRange: [0, 1], outputRange: [20, 14], }), color: this._animatedIsFocused.interpolate({ inputRange: [0, 1], outputRange: ['#aaa', '#000'], }), };
https://snack.expo.io/Hk8VCR-dZ?session_id=snack-session-AJ4vulSVw
Еще кое-что
Если в демо выше вы попробуете что-нибудь ввести, а затем убрать фокус с поля ввода, то увидите нечто странное.

К счастью, это довольно просто исправить. Нам нужно всего лишь поменять две строчки в коде.
Мы хотим проверить, пустое ли поле ввода и изменить состояние на “unfocused”, только если оба следующих условия выполняются:
- Значение поля ввода пустое;
- На поле нет фокуса.
В противном случае, мы хотим, чтобы применялся стиль “focused”, а замещающая надпись поднималась вверх.
Теперь, когда мы отслеживаем состояние поля ввода, мы можем легко получить доступ к его значению с помощью
this.props.
https://snack.expo.io/ByZBAC-dZ?session_id=snack-session-YNZSqhqOC
На этом всё. До встречи на бесплатном вебинаре.
