Создание новой заметки. FloatingActionButton. TextInputLayout. TextInputEditText.

Урок 24 — Создание новой заметки. FloatingActionButton. TextInputLayout. TextInputEditText.

В этом уроке мы с вами научимся создавать и удалять заметки, при этом продолжая изучать Material Design.

FloatingActionButton

FloatingActionButton — один из часто используемых компонентов Material Design.

Как ясно из названия, это кнопка, которая висит над контентом и предназначена для выполнения основного действия на текущем экране.

FloatingActionButton в Android
FloatingActionButton в Android

Размеры FloatingActionButton

Эта кнопка может быть двух размеров: стандартного или маленького.

FloatingActionButton стандартного размера
FloatingActionButton стандартного размера

В случае использования стандартного варианта, FloatingActionButton имеет размер 56x56 dp. Размер иконки внутри кнопки — 24x24 dp.

FloatingActionButton маленького размера
FloatingActionButton маленького размера

Уменьшенный вариант имеет размер 40x40 dp, при этом размер иконки внутри кнопки остаётся неизменным — 24x24 dp.

В обоих вариантах расстояние от краёв экрана не должно быть меньше 16 dp на телефонах и 24 dp на планшетах и десктопах.

Использование FloatingActionButton

В нашем приложении мы будем использовать FloatingActionButton для создания заметки.

Давайте же приступим к практике. Откройте файл activity_main.xml и измените его следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.skillberg.notes.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <include layout="@layout/toolbar" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/notes_rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/create_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_anchor="@id/notes_rv"
        app:layout_anchorGravity="bottom|end" />

</android.support.design.widget.CoordinatorLayout>

Среди атрибутов вы видите два незнакомых ранее:

  • layout_anchor указывает на View, относительно которого будет показываться FloatingActionButton. Мы ссылаемся на RecyclerView.
  • layout_anchorGravity задаёт позиционирование относительно того элемента, на который мы ссылаемся. В нашем случае кнопка будет отображаться внизу справа (или слева на RTL локалях) относительно RecyclerView.

Запустите приложение:

FloatingActionButton в нашем приложении
FloatingActionButton в нашем приложении

Как видите, кнопка отображается, но на ней нет иконки.

Для начала нужно создать иконку. Мы уже делали это ранее, но теперь для примера создадим векторную иконку:

Создание векторной иконки
Создание векторной иконки

Нажмите на кнопку выбора иконки:

Кнопка выбора иконки
Кнопка выбора иконки

Далее выберите иконку "Create":

Иконка "Create"
Иконка "Create"

Размер оставляем дефолтным. В итоге получим вот такое окно:

Иконка создана, теперь установим её во FloatingActionButton. Но прежде нам нужно решить одну проблему: векторные изображения поддерживаются только на Android Lollipop и выше, а на более ранних версиях они просто так работать не будут.

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

Для этого откройте build.gradle и добавьте следующую строку в секцию defaultConfig: vectorDrawables.useSupportLibrary = true.

В итоге ваш build.gradle должен выглядеть примерно так:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.2'
    defaultConfig {
        applicationId "com.skillberg.notes"
        minSdkVersion 17
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        vectorDrawables.useSupportLibrary = true
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.android.support:recyclerview-v7:26.1.0'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.android.support:cardview-v7:26.1.0'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
}

Отлично, теперь в activity_main.xml добавьте к FloatingActionButton вот такой атрибут:

app:srcCompat="@drawable/ic_create_24dp"

Запустите приложение:

Иконка в FloatingActionButton
Иконка в FloatingActionButton

Неплохо, но иконка чёрная, а должна быть белой.

Это не беда — поскольку FloatingActionButton — это, по сути, навороченный ImageView, мы можем изменить цвет иконки, используя атрибут android:tint. Добавьте его к кнопке, и посмотрите, что получится:

android:tint="@android:color/white"

FloatingActionButton с белой иконкой
FloatingActionButton с белой иконкой

Супер!

Обработка нажатий на FloatingActionButton

Обработка нажатий на FloatingActionButton работает точно так же, как и на любых других View.

В конце метода MainActivity.onCreate() найдите кнопку и добавьте на неё обработчик кликов:

findViewById(R.id.create_fab).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Здесь будет обрабатываться клик
    }
});

Что мы будем делать при нажатии? Просто запустим новую Activity, в которой будет создаваться заметка.

Создайте новую Activity:

Создание новой Activity
Создание новой Activity

Так же нужно создать файл вёрстки для Activity:

Этот файл будет содержать следующее:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.skillberg.notes.CreateNoteActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <include layout="@layout/toolbar" />

    </android.support.design.widget.AppBarLayout>


</android.support.design.widget.CoordinatorLayout>

В CreateNoteActivity установим его в качестве ContentView и зададим Toolbar:

public class CreateNoteActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_create_note);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
}

Ну и, конечно, не забудьте зарегистрировать Activity в манифесте:

<activity android:name=".CreateNoteActivity" />

Теперь мы можем запустить CreateNoteActivity в обработчике кликов FloatingActionButton в MainActivity:

@Override
public void onClick(View v) {
    Intent intent = new Intent(MainActivity.this, CreateNoteActivity.class);
    startActivity(intent);
}

При нажатии на кнопку Activity запустится:

CreateNoteActivity, запущенная нажатием на FloatingActionButton
CreateNoteActivity, запущенная нажатием на FloatingActionButton

Отлично!

Создание заметки

Для того, чтобы создать новую заметку, нам нужен интерфейс. Мы обойдёмся двумя уже знакомыми нам ViewEditText. Один из них будет для заголовка заметки, второй — для текста.

TextInputLayout

Чтобы сделать процесс ввода данных более очевидным для пользователя, принято использовать подсказки. Они есть и в обычном EditText, однако, будет правильным использовать вот такие поля:

TextInputLayout
TextInputLayout

Они понятны для пользователя, содержат подсказки и, что немаловажно, могут отображать сообщения об ошибках:

TextInputLayout с сообщением об ошибке
TextInputLayout с сообщением об ошибке

Создаются они совсем несложно — в Support-библиотеке есть специальный виджет TextInputLayout.

В activity_create_note.xml создайте контейнер для наших будущих View. Для этого вполне подойдёт вертикальный LinearLayout.

Поскольку мы не знаем, сколько текста будет вводить пользователь (высота текста может легко превысить высоту экрана), будет не лишним обернуть LinearLayout в ScrollView, который позволит скроллить контент:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.skillberg.notes.CreateNoteActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <include layout="@layout/toolbar" />

    </android.support.design.widget.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
        </LinearLayout>

    </ScrollView>


</android.support.design.widget.CoordinatorLayout>

Обратите внимание, что ни в коем случае нельзя задавать высоту дочернего элемента ScrollView равной match_parent, так как по сути внутренняя высота ScrollView бесконечна.

Кроме того, нельзя добавлять в ScrollView более одного дочернего View. Если нужно добавить несколько дочерних View, нужно добавлять их в контейнере (как мы сейчас и делаем).

Внутрь LinearLayout добавьте следующую разметку:

<android.support.design.widget.TextInputLayout
    android:id="@+id/title_til"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.design.widget.TextInputEditText
        android:id="@+id/title_et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/hint_title"
        android:inputType="textCapSentences" />

</android.support.design.widget.TextInputLayout>

Как видите, TextInputLayout служит контейнером для EditText.

Кроме того, вы могли обратить внимание, что мы используем TextInputEditText, а не просто EditText. Он почти ничем не отличается от обычного EditText, кроме улучшенной поддержки TextInputLayout.

В атрибут android:hint установлен текст подсказки (я заранее вынес его в ресурсы). Значение textCapSentences в атрибуте android:inputType говорит о том, что первая буква каждого предложения будет заглавной.

Запустив приложение, вы увидите следующее:

TextInputEditText внутри TextInputLayout
TextInputEditText внутри TextInputLayout

Подсказка поднялась вверх. Если фокус из поля пропадёт, то она сместится вниз и будет выглядеть так же, как и в обычном EditText.


Продолжение доступно на платных тарифах

Это недорого — всего от 440 ₽ в месяц!


ВЫБРАТЬ ТАРИФ


Продолжение доступно после регистрации

Все уроки на сайте доступны абсолютно бесплатно после регистрации.

Регистрация займёт меньше минуты ;)