Вступление
В этом уроке я снова расскажу о дизайне материалов. Google I / O 2015 был важным событием для каждого разработчика Android, и дизайн, конечно же, был частью обсуждения.
Google понял, что обратная совместимость — самая сложная часть реализации дизайна материала. Конечно, библиотеки поддержки, такие как appcompat-v4 и appcompat-v7 , являются частью решения. Однако Theme.AppCompat
не реализует каждый элемент материала, используемый в официальных приложениях Google. Одной из функций, отсутствующих в теме AppCompat, является возможность размещать плавающую метку поверх виджета EditText
. Вы можете видеть, что я имею в виду в следующем примере.
Во время Google I / O 2015 команда Android выпустила новую библиотеку поддержки, Библиотеку поддержки дизайна . Это очень удобно для решения подобных проблем. Этот учебник покажет вам, как использовать новый виджет TextInputLayout
который включен в Библиотека поддержки дизайна.
1. Реализация TextInputLayout
Шаг 1: Создайте новый проект
В Android Studio выберите « Новый»> «Новый проект» в меню « Файл» . Введите необходимую информацию для настройки проекта и создания проекта. В моем примере я нацелил проект на API 7 , который является минимальным уровнем API, поддерживаемым библиотекой поддержки проектирования. Благодаря такому низкому уровню API ваше приложение будет работать практически на всех устройствах Android. Я назвал основной вид деятельности LoginActivity
и его файл макета activity_login.xml .
После настройки проекта удалите в основном упражнении onCreateOptionsMenu
и метод onOptionsItemSelected
который автоматически генерируется Android Studio. Экран входа в систему, который мы собираемся создать, не нуждается в меню, поэтому можно удалить эти методы. Не забудьте также удалить файл меню XML, который находится в папке res / menu .
Шаг 2. Импорт библиотек поддержки
Чтобы использовать виджет TextInputLayout
, вам нужно импортировать две библиотеки. Первый — appcompat-v7 , который обеспечивает обратную совместимость стилей материала. Второй — библиотека поддержки дизайна .
В файле build.gradle вашего проекта добавьте следующие строки в зависимости проекта:
1
2
3
4
5
6
|
dependencies {
compile fileTree(dir: ‘libs’, include: [‘*.jar’])
compile ‘com.android.support:design:22.2.0’
compile ‘com.android.support:appcompat-v7:22.2.0’
}
|
Если Gradle не просит автоматически синхронизировать ваш проект, выберите Make module ‘app’ в меню Build или нажмите F9 . Таким образом, система сборки Android Studio автоматически выберет необходимые ресурсы, и вы сможете импортировать любые необходимые классы.
Шаг 3: Дизайн пользовательского интерфейса
Пользовательский интерфейс этого проекта очень прост. Он показывает приветственную метку (которую можно легко заменить на логотип, если он у вас есть) и два элемента EditText
, один для имени пользователя и один для пароля. Макет также включает в себя кнопку, которая запускает последовательность входа в систему. Цвет фона приятный, ровный, светло-серый.
Еще одна важная деталь, о которой стоит помнить, — это правильная настройка атрибута inputType
элементов EditText
. Для inputType
первого элемента EditText
должно быть установлено значение textEmail
а для второго textPassword
. Вот как должен выглядеть макет.
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
<LinearLayout xmlns:android=»https://schemas.android.com/apk/res/android»
xmlns:tools=»http://schemas.android.com/tools»
android:background=»#e3e3e3″
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:padding=»@dimen/activity_horizontal_margin»
tools:context=».LoginActivity»
android:orientation=»vertical»>
<RelativeLayout
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:layout_weight=»0.5″
android:orientation=»vertical»>
<TextView
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:layout_centerInParent=»true»
android:gravity=»center»
android:text=»Welcome»
android:textSize=»30sp»
android:textColor=»#333333″/>
</RelativeLayout>
<LinearLayout
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:layout_weight=»0.5″
android:orientation=»vertical»>
<EditText
android:id=»@+id/username»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:inputType=»textEmailAddress»/>
<EditText
android:id=»@+id/password»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:inputType=»textPassword»/>
<Button
android:id=»@+id/btn»
android:layout_marginTop=»4dp»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:text=»Login»/>
</LinearLayout>
</LinearLayout>
|
Вы также можете избавиться от панели приложения, ранее известной как панель действий, отредактировав файл style.xml, как показано ниже.
1
2
|
<style name=»AppTheme» parent=»Theme.AppCompat.Light.NoActionBar»>
</style>
|
Шаг 4: Использование TextInputLayout
Мы наконец добрались до самой интересной части этого урока. Виджет TextInputLayout
ведет себя точно так же, как и LinearLayout
, это просто оболочка. TextInputLayout
принимает только один дочерний элемент, похожий на ScrollView
. Дочерний элемент должен быть элементом EditText
.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<android.support.design.widget.TextInputLayout
android:id=»@+id/usernameWrapper»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»>
<EditText
android:id=»@+id/username»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:inputType=»textEmailAddress»
android:hint=»Username»/>
</android.support.design.widget.TextInputLayout>
|
Обратите внимание, что я указал другой параметр в элементе EditText
, hint
. Как вы уже знаете, этот атрибут позволяет отображать пользовательскую подсказку, когда в EditText
нет содержимого. Как только пользователь начинает печатать, подсказка исчезает. Это не здорово, потому что они теряют контекст информации, которую они вводят.
Благодаря TextInputLayout
это больше не будет проблемой. В то время как один только EditText
будет скрывать подсказку после ввода первого символа, при переносе в TextInputLayout
подсказка станет плавающей меткой над EditText
. Хорошая анимация материала тоже включена.
Далее, давайте сделаем то же самое для поля пароля.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<android.support.design.widget.TextInputLayout
android:id=»@+id/passwordWrapper»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:layout_below=»@id/usernameWrapper»
android:layout_marginTop=»4dp»>
<EditText
android:id=»@+id/password»
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:inputType=»textPassword»
android:hint=»Password»/>
</android.support.design.widget.TextInputLayout>
|
Если вы запустите приложение сейчас, ничего не произойдет. Конечно, атрибут подсказки EditText
будет вести себя как положено. Однако нет анимации материала и плавающих надписей. Это почему? Нам все еще не хватает кода, чтобы все работало.
Шаг 5: Настройка подсказок
Ниже метода setContentView
инициализируйте ссылки на представления TextInputLayout
.
1
2
|
final TextInputLayout usernameWrapper = (TextInputLayout) findViewById(R.id.usernameWrapper);
final TextInputLayout passwordWrapper = (TextInputLayout) findViewById(R.id.passwordWrapper);
|
Чтобы анимировать плавающую метку, вам просто нужно установить подсказку, используя метод setHint
.
1
2
|
usernameWrapper.setHint(«Username»);
passwordWrapper.setHint(«Password»);
|
И вы сделали. Теперь ваш экран входа в систему соответствует правилам оформления материалов. Запустите приложение, чтобы увидеть ваш красивый экран входа в систему.
2. Обработка ошибок
Еще одна приятная особенность TextInputLayout
— способ обработки ошибок. Проверяя введенные данные, вы не позволяете пользователям неправильно вводить свой адрес электронной почты или вводить слишком короткий пароль.
При проверке входных данных серверная часть будет обрабатывать неверные учетные данные, ошибки будут генерироваться и отправляться клиенту, а затем показываться (ожидающему) пользователю. Значительная потеря времени и плохой пользовательский опыт. Вы должны проверить ввод пользователя перед отправкой его на сервер.
Шаг 1: Реализация метода onClick
Сначала вы должны обработать нажатие кнопки. Есть много способов обрабатывать нажатия кнопок. Одним из них является написание собственного метода и указание его в XML-файле с помощью атрибута onClick
. Я предпочитаю setOnClickListener
, но это действительно вопрос личного вкуса.
1
2
3
4
5
6
|
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// STUB
}
});
|
Мы знаем, что если этот метод вызывается, пользователю больше не нужна клавиатура. К сожалению, Android не скрывает виртуальную клавиатуру автоматически, если вы не скажете это. Вызовите hideKeyboard
в теле метода hideKeyboard
.
1
2
3
4
5
6
7
|
private void hideKeyboard() {
View view = getCurrentFocus();
if (view != null) {
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
|
Шаг 2: Проверка ввода
Прежде чем устанавливать метки ошибок, мы должны определить, что является ошибкой, а что нет. Мы предполагаем, что имя пользователя должно быть адресом электронной почты, и мы хотим запретить пользователям вводить неверный адрес электронной почты.
Проверка адреса электронной почты немного сложна. Мы должны полагаться на регулярные выражения. Вы также можете использовать библиотеку Apache Commons, если хотите.
Я написал следующее регулярное выражение, используя рекомендации, предложенные Википедией относительно достоверности электронной почты.
1
|
/^[a-zA-Z0-9#_~!$&'()*+,;=:.»(),:;<>@\[\]\\]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/
|
Смысл этого регулярного выражения довольно прост. Он состоит из трех групп захвата. Первый соответствует буквам алфавита (верхний и нижний регистр), числам и серии принятых символов. Из-за квантификатора +
эта группа соответствует строке, состоящей как минимум из одного символа.
Далее, есть символ @
, который, конечно, требуется в каждом адресе электронной почты. Вторая группа принимает только буквы, цифры и дефисы. Длина также должна быть не менее одного ( ]+
).
Наконец, есть последняя группа, которая содержит точку и целью которой является сопоставление поддоменов и TLD. Его квантификатором является звезда *
, что означает, что эта группа ищет строку, длина которой может быть равна нулю или более. Фактически, адреса электронной почты с доменом, но без TLD, действительно действительны.
Поскольку мы хотим проверить String
, мы должны полагаться на классы Pattern
и Matcher
, включенные в пакет java.util.regex . Импортируйте эти классы в свою деятельность, а затем реализуйте следующий метод:
1
2
3
4
5
6
7
8
|
private static final String EMAIL_PATTERN = «^[a-zA-Z0-9#_~!$&'()*+,;=:.\»(),:;<>@\\[\\]\\\\]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$»;
private Pattern pattern = Pattern.compile(EMAIL_PATTERN);
private Matcher matcher;
public boolean validateEmail(String email) {
matcher = pattern.matcher(email);
return matcher.matches();
}
|
Проверка поля пароля намного проще. В большинстве организаций применяются разные политики для проверки правильности пароля, но для каждой из них установлена минимальная длина. Разумное правило заключается в том, что пароль никогда не должен быть короче шести символов.
1
2
3
|
public boolean validatePassword(String password) {
return password.length() > 5;
}
|
Шаг 3: Получение данных
Как я уже сказал, TextInputLayout
— это просто оболочка, но в отличие от LinearLayout
и ScrollView
, вы можете получить его дочерний элемент с помощью специального метода getEditText
. Нет необходимости использовать findViewById
.
Если TextInputLayout
не содержит EditText
, getEditText
возвращает null
поэтому будьте осторожны с NullPointException
.
01
02
03
04
05
06
07
08
09
10
|
public void onClick(View v) {
hideKeyboard();
String username = usernameWrapper.getEditText().getText().toString();
String password = usernameWrapper.getEditText().getText().toString();
// TODO: Checks
// TODO: Login
}
|
Шаг 4: Отображение ошибок
Обработка ошибок TextInputLayout
легко и быстро. Обязательные методы — setErrorEnabled
и setError
.
setError
устанавливает красное сообщение об ошибке, которое будет отображаться под EditText
. Если переданный параметр является null
, сообщение об ошибке очищается. Он также меняет цвет всего виджета EditText
на красный.
setErrorEnabled
включает функцию ошибки. Это напрямую влияет на размер макета, увеличивая нижний отступ, чтобы освободить место для метки ошибки. Включение этой функции перед установкой сообщения об ошибке с помощью setError
означает, что этот макет не изменит размер при отображении ошибки. Вы должны сделать несколько тестов, комбинирующих эти два метода, чтобы вы на самом деле видели о чем я говорю
Еще одним интересным фактом является то, что если функция ошибок еще не была включена и вы вызываете setError
передавая ненулевой параметр, то setErrorEnabled(true)
будет вызываться автоматически.
Теперь, когда мы определили, что правильно, а что нет, и мы знаем, как извлекать данные и отображать возможные ошибки, реализация метода onClick
становится тривиальной.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public void onClick(View v) {
hideKeyboard();
String username = usernameWrapper.getEditText().getText().toString();
String password = usernameWrapper.getEditText().getText().toString();
if (!validateEmail(username)) {
usernameWrapper.setError(«Not a valid email address!»);
} else if (!validatePassword(password)) {
passwordWrapper.setError(«Not a valid password!»);
} else {
usernameWrapper.setErrorEnabled(false);
passwordWrapper.setErrorEnabled(false);
doLogin();
}
}
|
Я добавил метод doLogin
, но в настоящее время он пуст, поскольку это выходит за рамки данного руководства.
1
2
3
4
|
public void doLogin() {
Toast.makeText(getApplicationContext(), «OK! I’m performing login.», Toast.LENGTH_SHORT).show();
// TODO: login procedure;
}
|
3. Стайлинг
Возможно, вы захотите сделать еще одну вещь, изменив цвет виджета TextInputLayout
. По умолчанию тема AppCompact
устанавливает зеленый цвет, но довольно часто этот цвет конфликтует с вашей цветовой палитрой.
Google очень хорошо написал Библиотеку поддержки дизайна. Цвет каждого виджета рисуется непосредственно из цветов темы, указанных в вашем файле style.xml . Просто откройте его и добавьте элемент colorAccent
в вашу активную тему, чтобы изменить цветовую схему формы.
1
2
3
|
<style name=»AppTheme» parent=»Theme.AppCompat.Light.NoActionBar»>
<item name=»colorAccent»>#3498db</item>
</style>
|
Вывод
В этом уроке мы увидели, как реализовать новый элемент макета TextInputLayout
, благодаря только что представленной библиотеке поддержки проектирования.
Парадигма дизайна, которую реализует этот виджет, позволяет пользователям никогда не терять контекст вводимой ими информации, и она была фактически представлена Google в прошлом году вместе с Material Design.
В то время не было библиотеки поддержки, предоставляющей разработчикам возможность задействовать этот виджет в своих проектах до Google I / O 2015. Теперь, если ваше приложение ожидает какой-то ввод данных, вы, наконец, будете по-настоящему совместимы с дизайном материалов. ,