Урок 13. Практическое занятие. Наполнение Toolbar вложенными элементами на экране SearchUsersActivity – Devcolibri – Android для начинающих

Урок 13. Практическое занятие. Наполнение Toolbar вложенными элементами на экране SearchUsersActivity

Нам необходимо сделать тулбар такого вида:

 

search_users_toolbar.png

 

Здесь стандартным меню не обойдёшься, поэтому нам понадобится toolbar_search_user.xml-файл, который мы создавали во втором уроке. Сперва, как и с предыдущим тулбаром в файле activity_user_info.xml, добавим его в файл activity_search_users.xml:

 

activity_search_users.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/Toolbar">

    </android.support.v7.widget.Toolbar>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/users_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

 

Мы изменили корневой элемент с FrameLayout на LinearLayout, т.к. у нас появился второй вложенный элемент. Мы указали свойство android:orientation="vertical", чтобы элементы располагались вертикально.

А теперь просто добавим содержимое файла toolbar_search_user.xml, немного его изменив, внутрь элемента ToolbarToolbar является ViewGroup, поэтому в него можно помещать элементы, как и в любой другой контейнер. Единственный нюанс: Toolbar располагает элементы один над одним по умолчанию (как FrameLayout).

 

activity_search_users.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/Toolbar">

        <RelativeLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="8dp">

            <EditText
                android:id="@+id/search_edit_text"
                android:layout_width="match_parent"
                android:layout_marginEnd="20dp"
                android:layout_toStartOf="@+id/search_button"
                android:layout_height="wrap_content"
                android:hint="Введите имя"/>

            <Button
                android:id="@+id/search_button"
                android:layout_alignParentEnd="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Поиск"/>

        </RelativeLayout>

    </android.support.v7.widget.Toolbar>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/users_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

 

Единственное, что изменилось – атрибут android:layout_height="match_parent" у контейнера RelativeLayout. Т.к. нам необходимо, чтобы контейнер занимал всю высоту parent элемента (им является Toolbar).

Запустим приложение и перейдём на экран поиска пользователей:

 

SearchUsersToolbarRaw.png

 

Видим, что данные отобразились, но визуально они выглядят не очень.

Нам надо поменять стили у наших элементов EditText и Button.

Давайте усовершенствуем наш EditText:

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<EditText
    android:id="@+id/query_edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginEnd="10dp"
    android:layout_toStartOf="@+id/search_button"
    android:background="@null"
    android:maxLines="1"
    android:imeOptions="actionSearch"
    android:inputType="text"
    android:hint="@string/search_query_hint"/>

 

Объясним некоторые атрибуты:

  • android:maxLines="1" – означает, что EditText не будет поддерживать многострочный режим и весь текст будет распологаться в одну строку.
  • android:imeOptions="actionSearch" и android:inputType="text" добавляют в клавиатуру пользователя кнопку поиска, нажатие по которой в дальнейшем мы сможем обработать.
  • android:background="@null" убирает нижнюю линию, которая по умолчанию присуствует в EditText.

Также некоторые изменения претерпела кнопка поиска.

Добавление иконки шрифта Ionicons

Перед тем, как добавить кнопку, нам необходимо по аналогии со шрифтом font_awesome в проект добавить шрифт ionicons.

После этого нам нужно добавить строковый ресурс иконки поиска, которая располагается на сайте. Найти её можно используя название ion-android-search. После того, как нашли её, необходимо скопировать иконку, которая находится в блоке selectable, как показано на скрине.

 

IoniconsIcon.png

 

После этого просто создаём новый строковый ресурс с именем ion_search и вставляем то значение, которое мы скопировали:

 

strings.xml

1
2
3
4
<resources>
    <!-- Остальные элементы выше не изменились -->
    <string name="ion_search"></string>
</resources>

 

Видим, что иконка отобразилась корректно.

Вот как выглядит наша кнопка со всеми атрибутами:

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<Button
    android:id="@+id/search_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:layout_alignParentEnd="true"
    android:background="@drawable/transparent_gfx"
    android:fontFamily="@font/ionicons"
    android:text="@string/ion_search"
    android:textColor="@color/white"
    android:textSize="23sp"/>

 

Также мы используем атрибут android:background="@drawable/transparent_gfx". Пользовательский интерфейс должен быть интуитивно понятен для пользователя, поэтому он должен показывать некую реакцию на действия пользователя. В данном случае при нажатии на кнопку поиска её фон должен видоизменяться, тем самым показывая отзывчивость кнопки на действия пользователя. Более подробно об этом эффекте можно узнать из отрывка курса Material Design в Android. Ниже приведены файлы эффекта:

Нам нужно создать файл с названием transparent_gfx в папке drawable. Для этого кликните по папке правой кнопкой, выбрав элементы New -> Drawable resource file.

 

drawable/transparent_gfx.xml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true">
        <shape android:shape="oval">
            <solid android:color="@color/white_alpha" />
        </shape>
    </item>

    <item>
        <shape android:shape="oval">
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>

</selector>

Работа с вложенными в Toolbar элементами в java коде

Теперь мы можем работать с элементами тулбара как и с любыми другими элементами экрана. Давайте добавим Toolbar и его вложенные элементы в SearchUsersActivity.

 

SearchUsersActivity.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class SearchUsersActivity extends AppCompatActivity {

    // остальные элементы выше не изменились
    private Toolbar toolbar;
    private EditText queryEditText;
    private Button searchButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_users);
        initRecyclerView();

        toolbar = findViewById(R.id.toolbar);
        queryEditText = toolbar.findViewById(R.id.query_edit_text);
        searchButton = toolbar.findViewById(R.id.search_button);

        searchUsers();
    }
}

 

Ничего не обычного. Только вложенные элементы мы ищем используя toolbar.findViewById(). Это сделано для оптимизации поиска элементов. Поиск будет проходить только внутри Toolbar элемента, а не во всех элементах SearchUsersActivity.

Теперь давайте будем производить поиск пользователей не в методе onCreate, а добавим слушателей на нажатие кнопки поиска и на нажатие кнопки search внутри клавиатуры.

 

SearchUsersActivity.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SearchUsersActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // остальной код выше не изменился
        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                searchUsers();
            }
        });

        queryEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    searchUsers();
                    return true;
                }
                return false;
            }
        });
    }
}

 

Если вы сейчас запустите приложение, то не увидите в тулбаре кнопки «Назад» в левой его части. Её мы можем добавить, используя стандартный механизм тулбара:

 

SearchUsersActivity.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class SearchUsersActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // остальной код выше не изменился
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

 

Таким образом, мы сообщаем Activity о необходимости отобразить кнопку «Назад». По умолчанию кнопка назад не будет работать. Мы хотим, чтобы она работала как аппаратная кнопка «Назад». Для этого мы перехватываем нажатием кнопки в тулбаре и вызываем метод Activity onBackPressed().

Посмотрим, что у нас получилось в итоге:

 

Result.png

 

Отлично, поздравляем вас!

Кстати, мы можем удалить файл toolbar_search_user.xml, т.к. он нам больше не понадобится.

Полный листинг кода:

 

SearchUsersActivity.java

  1
  2
  3
  4
  5
  6
  7
  8
  9
 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
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package colibri.dev.com.colibritweet.activity;

import java.util.Arrays;
import java.util.Collection;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import colibri.dev.com.colibritweet.R;
import colibri.dev.com.colibritweet.adapter.UsersAdapter;
import colibri.dev.com.colibritweet.pojo.User;

public class SearchUsersActivity extends AppCompatActivity {
    private RecyclerView usersRecyclerView;
    private UsersAdapter usersAdapter;

    private Toolbar toolbar;
    private EditText queryEditText;
    private Button searchButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_users);
        initRecyclerView();

        toolbar = findViewById(R.id.toolbar);
        queryEditText = toolbar.findViewById(R.id.query_edit_text);
        searchButton = toolbar.findViewById(R.id.search_button);

        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                searchUsers();
            }
        });

        queryEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    searchUsers();
                    return true;
                }
                return false;
            }
        });

        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void searchUsers() {
        Collection<User> users = getUsers();
        usersAdapter.setItems(users);
    }

    private Collection<User> getUsers() {
        return Arrays.asList(
                new User(
                        1L,
                        "http://i.imgur.com/DvpvklR.png",
                        "DevColibri",
                        "@devcolibri",
                        "Sample description",
                        "USA",
                        42,
                        42
                ),

                new User(
                        2L,
                        "https://pbs.twimg.com/profile_images/782474226020200448/zDo-gAo0_400x400.jpg",
                        "Elon Musk",
                        "@elonmusk",
                        "Hat Salesman",
                        "Boring",
                        14,
                        13
                )
        );
    }

    private void initRecyclerView() {
        usersRecyclerView = findViewById(R.id.users_recycler_view);
        usersRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        UsersAdapter.OnUserClickListener onUserClickListener = new UsersAdapter.OnUserClickListener() {
            @Override
            public void onUserClick(User user) {
                Intent intent = new Intent(SearchUsersActivity.this, UserInfoActivity.class);
                intent.putExtra("userId", user.getId());
                startActivity(intent);
            }
        };
        usersAdapter = new UsersAdapter(onUserClickListener);
        usersRecyclerView.setAdapter(usersAdapter);
    }
}

 

activity_search_users.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/Toolbar">

        <RelativeLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="8dp">

            <EditText
                android:id="@+id/query_edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginEnd="10dp"
                android:layout_toStartOf="@+id/search_button"
                android:background="@null"
                android:maxLines="1"
                android:imeOptions="actionSearch"
                android:inputType="text"
                android:hint="@string/search_query_hint"/>

            <Button
                android:id="@+id/search_button"
                android:layout_width="?attr/actionBarSize"
                android:layout_height="?attr/actionBarSize"
                android:layout_alignParentEnd="true"
                android:background="@drawable/transparent_gfx"
                android:fontFamily="@font/ionicons"
                android:text="@string/ion_search"
                android:textColor="@color/white"
                android:textSize="23sp"/>

        </RelativeLayout>

    </android.support.v7.widget.Toolbar>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/users_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

 

В результате данного урока мы:

  • отработали навыки работы с Toolbar;
  • узнали, каким образом наполнить Toolbar пользовательскими элементами.
УВИДЕТЬ ВСЕ Добавить заметку
Вы
Добавить ваш комментарий
 

Сайт использует cookie-файлы для того, чтобы вам было удобнее им пользоваться. Для продолжения работы с сайтом, вам необходимо принять использование cookie-файлов.

Я ознакомлен(а)