Статьи

Общие макеты приложений React Native: страница входа

В этой серии вы узнаете, как использовать React Native для создания макетов страниц, обычно используемых в мобильных приложениях. Макеты, которые вы будете создавать, не будут функциональными — вместо этого, основной целью этой серии является то, чтобы вы запачкали руки при размещении контента в ваших приложениях React Native.

Если вы новичок в разработке приложений React Native или стилей в целом, посмотрите мой предыдущий учебник:

Чтобы следовать этой серии, я призываю вас сначала попытаться воссоздать каждый экран самостоятельно, прежде чем вы прочитаете мои пошаговые инструкции в руководстве. Вы действительно не получите много пользы от этого урока, просто прочитав его! Попробуйте сначала, прежде чем искать ответы здесь. Если вам удалось сделать его похожим на исходный экран, сравните вашу реализацию с моей. Тогда решите для себя, какой из них лучше!

В этой первой части серии вы создадите следующую страницу входа в систему:

пример страницы входа

Страница входа в систему обычно используется в качестве начальной страницы для приложений, которые требуют, чтобы у пользователей была учетная запись.

Вот пара примеров этого типа макета в дикой природе:

Страница входа в Soundcloud

Первым шагом, конечно же, является создание нового проекта React Native:

1
react-native init react-native-common-screens

После настройки проекта откройте файл index.android.js и замените код по умолчанию следующим index.android.js :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
import React, { Component } from ‘react’;
import {
  AppRegistry
} from ‘react-native’;
 
import Login from ‘./src/pages/Login’;
 
export default class ReactNativeCommonScreens extends Component {
 
  render() {
    return (
      <Login />
    );
  }
 
}
 
AppRegistry.registerComponent(‘ReactNativeCommonScreens’, () => ReactNativeCommonScreens);

Создайте папку src/pages и создайте внутри нее файл Login.js .

Вам также понадобится пакет react-native-vector-icons . Это специально используется для отображения значка Facebook для кнопки входа в Facebook.

1
npm install —save react-native-vector-icons

Откройте файл android/app/build.gradle и добавьте ссылку на пакет:

1
2
3
4
dependencies {
    //rest of the dependencies are here at the top
    compile project(‘:react-native-vector-icons’) //add this
}

Сделайте то же самое с файлом android/settings.gradle , добавив следующее внизу:

1
2
include ‘:react-native-vector-icons’
project(‘:react-native-vector-icons’).projectDir = new File(rootProject.projectDir, ‘../node_modules/react-native-vector-icons/android’)

Откройте android/app/src/main/java/com/react-native-common-screens/MainApplication.java и импортируйте пакет:

1
2
3
4
import java.util.Arrays;
import java.util.List;
 
import com.oblador.vectoricons.VectorIconsPackage;

Наконец, инициализируйте пакет:

1
2
3
4
5
6
7
@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      new VectorIconsPackage() //add this
  );
}

Хорошо, теперь, когда вы попытались кодировать макет самостоятельно (без обмана, верно?), Я покажу вам, как я построил свою реализацию. Откройте файл src/pages/Login.js и импортируйте то, что вам нужно:

01
02
03
04
05
06
07
08
09
10
11
import React, { Component } from ‘react’;
 
import {
  StyleSheet,
  Text,
  View,
  TextInput,
  ScrollView
} from ‘react-native’;
 
import Icon from ‘react-native-vector-icons/FontAwesome’;

Помимо стандартных компонентов React и react-native-vector-icons , вам также необходимо включить три пользовательских компонента:

1
2
3
import Container from ‘../components/Container’;
import Button from ‘../components/Button’;
import Label from ‘../components/Label’;

Первый — это Container ( src/components/Container.js ), работа которого заключается в добавлении нижнего поля к тому, что он переносит. Это звучит тривиально, и да, вы можете просто использовать View и добавлять одни и те же стили каждый раз, когда захотите его использовать. Преимущество этого предложения в том, что вам не нужно применять одни и те же стили к представлению несколько раз, и это также позволяет вам повторно использовать компонент каждый раз, когда вам нужно добавить нижнее поле к чему-либо.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { Component } from ‘react’;
 
import {
  StyleSheet,
  View
} from ‘react-native’;
 
const Container = (props) => {
    return (
        <View style={styles.labelContainer}>
            { props.children }
        </View>
    );
}
 
const styles = StyleSheet.create({
    labelContainer: {
        marginBottom: 20
    }
});
 
export default Container;

Компонент Button ( src/components/Button.js ), как следует из названия, используется для создания кнопок. Если он присутствует, то он выплевывает любой дочерний компонент, добавленный в него. В противном случае он выводит компонент Text который показывает текст внутри кнопки. Также добавлен стиль по умолчанию, но он не будет использоваться, если в noDefaultStyles присутствует noDefaultStyles . Уникальные стили кнопок, передаваемые из реквизита, также являются необязательными.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import React, { Component } from ‘react’;
 
import {
  StyleSheet,
  Text,
  TouchableHighlight,
} from ‘react-native’;
 
const Button = (props) => {
     
    function getContent(){
        if(props.children){
            return props.children;
        }
        return <Text style={props.styles.label}>{props.label}</Text>
    }
 
    return (
        <TouchableHighlight
            underlayColor=»#ccc»
            onPress={props.onPress}
            style={[
                props.noDefaultStyles ?
                props.styles ?
        >
            { getContent() }
        </TouchableHighlight>
    );
}
 
const styles = StyleSheet.create({
    button: {
        alignItems: ‘center’,
        justifyContent: ‘center’,
        padding: 20
    },
});
 
export default Button;

Наконец, есть компонент Label ( src/components/Label.js ), который в основном представляет собой просто Text компонент с некоторым предопределенным стилем.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import React, { Component } from ‘react’;
 
import {
  StyleSheet,
  Text,
} from ‘react-native’;
 
const Label = (props) => {
    return (
        <Text
            style={props.styles && props.styles.textLabel ?
        >
            {props.text}
        </Text>
    );
}
 
const styles = StyleSheet.create({
    textLabel: {
        fontSize: 20,
        fontWeight: ‘bold’,
        fontFamily: ‘Verdana’,
        marginBottom: 10,
        color: ‘#595856’
    }
});
 
export default Label;

Теперь вы можете перейти к реальной странице входа. Внутри метода render() оберните все в компонент ScrollView . Это очень важно, если вы хотите, чтобы ваше приложение могло обслуживать любые размеры устройств и ориентацию экрана.

Чаще всего, независимо от того, насколько малой высоты, по вашему мнению, будет расходовать ваш контент, всегда будет устройство, которое не сможет отобразить его полностью. Таким образом возникает необходимость в полосах прокрутки для прокрутки контента.

1
2
3
4
5
6
7
8
9
export default class Login extends Component {
  render() {
    return (
        <ScrollView style={styles.scroll}>
        …
        </ScrollView>
    );
  }
}

Далее инициализируем стили:

1
2
3
const styles = StyleSheet.create({
 
});

Примените следующие стили к ScrollView . flexDirection является необязательным, но хорошей практикой является его явное определение, чтобы будущие разработчики точно знали, как раскладывается основное содержимое приложения, просто взглянув на код.

1
2
3
4
5
scroll: {
    backgroundColor: ‘#E1D7D8’,
    padding: 30,
    flexDirection: ‘column’
},

Если посмотреть на снимок экрана, сделанный ранее, первым элементом контента, который вы хотите добавить, является тот, что вверху, и это кнопка забытого пароля. Обратите внимание, что реквизиты onPress предоставляются, потому что underlayColor фактически не будет применен, если не будет предоставлена ​​функция для нажатия кнопки.

1
2
3
4
5
6
<Container>
    <Button
        label=»Forgot Login/Pass»
        styles={{button: styles.alignRight, label: styles.label}}
        onPress={this.press.bind(this)} />
</Container>

Используемые для этого стили довольно alignSelf: 'flex-end' за исключением alignSelf: 'flex-end' . Это говорит React Native о расположении элемента в самом конце текущей строки. alignSelf является эквивалентом alignItems для определения выравнивания самого элемента, а не его дочерних элементов. Использование flex-end позволяет достичь эффекта, аналогичного эффекту float: right в CSS.

1
2
3
4
5
6
7
label: {
    color: ‘#0d8898’,
    fontSize: 20
},
alignRight: {
    alignSelf: ‘flex-end’
},

Далее идут два текстовых поля вместе с их ярлыками.

01
02
03
04
05
06
07
08
09
10
11
12
13
<Container>
    <Label text=»Username or Email» />
    <TextInput
        style={styles.textInput}
    />
</Container>
<Container>
    <Label text=»Password» />
    <TextInput
        secureTextEntry={true}
        style={styles.textInput}
    />
</Container>

На данный момент страница должна выглядеть следующим образом:

начальная стилизация страницы входа

Вот стиль для textInput :

1
2
3
4
5
textInput: {
    height: 80,
    fontSize: 30,
    backgroundColor: ‘#FFF’
},

Теперь вы, возможно, начали замечать, почему компонент Container важен. Это позволяет вам инкапсулировать стили по умолчанию, чтобы не объявлять их заново в каждом файле. Это основной принцип React: вы всегда должны стремиться к повторному использованию компонентов каждый раз, когда видите возможность.

Кнопка входа в Facebook немного отличается от кнопок, которые вы создали ранее. На этот раз в нем есть контент, который отображает значок вместе с текстом. Они добавляются вместо label для дополнительной настройки содержимого кнопки.

01
02
03
04
05
06
07
08
09
10
11
12
<Container>
    <Button
        styles={{button: styles.transparentButton}}
        onPress={this.press.bind(this)}
    >
        <View style={styles.inline}>
            <Icon name=»facebook-official» size={30} color=»#3B5699″ />
            <Text style={[styles.buttonBlueText, styles.buttonBigText]}> Connect </Text>
            <Text style={styles.buttonBlueText}>with Facebook</Text>
        </View>
    </Button>
</Container>

Как только это будет добавлено, страница должна выглядеть следующим образом:

страница входа в систему без стилей Facebook кнопка входа

Добавьте стили для кнопки входа в Facebook:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
transparentButton: {
    marginTop: 30,
    borderColor: ‘#3B5699’,
    borderWidth: 2
},
buttonBlueText: {
    fontSize: 20,
    color: ‘#3B5699’
},
buttonBigText: {
    fontSize: 20,
    fontWeight: ‘bold’
},
inline: {
    flexDirection: ‘row’
},

Здесь действительно ничего не стоит отметить, за исключением styles.inline , который используется в качестве вспомогательного класса для горизонтального размещения всех элементов внутри него. Это дает эффект, аналогичный использованию <span> в HTML для переноса текста, который вы хотите отобразить встроенным. В CSS это может быть достигнуто с помощью display: inline или display: inline-block .

страница входа добавлены стили кнопок входа в Facebook

Последние элементы на этом экране — кнопки « Вход» и « Отмена» . Им нужно больше места над ними, чем над другими элементами, поэтому лучше обернуть их в контейнер ( footer ) и применить к нему marginTop . Это имеет больше смысла, чем объявление нового стиля только для этих кнопок.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<View style={styles.footer}>
    <Container>
        <Button
            label=»Sign In»
            styles={{button: styles.primaryButton, label: styles.buttonWhiteText}}
            onPress={this.press.bind(this)} />
    </Container>
    <Container>
        <Button
            label=»CANCEL»
            styles={{label: styles.buttonBlackText}}
            onPress={this.press.bind(this)} />
    </Container>
</View>
страница входа добавлена ​​кнопка входа и отмены

Наконец, добавьте стиль для кнопок Вход и Отмена :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
buttonWhiteText: {
    fontSize: 20,
    color: ‘#FFF’,
},
buttonBlackText: {
    fontSize: 20,
    color: ‘#595856’
},
primaryButton: {
    backgroundColor: ‘#34A853’
},
footer: {
   marginTop: 100
}
Заполненная страница входа

Наконец, не забудьте определить код, который будет выполняться при нажатии любой из кнопок!

1
2
3
press() {
  //execute any code here
}

Это оно! В этом руководстве вы успешно создали страницу входа, используя свои знания Flexbox. Кроме того, вы также узнали, как использовать стороннюю библиотеку React Native Vector Icons, чтобы легко добавлять значки в ваше приложение. Как мое решение сравнилось с вашим? Дайте нам знать в дискуссионном форуме ниже.

В следующем уроке из этой серии вы узнаете, как создать экран календаря. А пока ознакомьтесь с другими нашими учебниками по React Native и Flexbox.

  • Введение в модуль CSS Flexbox

  • Начните с React Native Layouts

  • Создайте социальное приложение с React Native

  • Как создать полосатую навигацию с Flexbox

  • Анимируйте свое приложение React Native

  • Как создать приложение для обнаружения лиц с помощью React Native