Урок 13. Работа с Toolbar и menu на примере UserInfoActivity
Элемент Toolbar предназначен для быстрого и удобного доступа пользователя к часто используемым функциям. Создать его можно используя как упрощённый вариант, в котором о многом уже позаботились разработчики системы Android , так и полностью управляя всеми внутренними компонентами. В данном уроке мы рассмотрим упрощённый вариант.
На главном экране приложения с детальной информацией о пользователе нам необходимо создать такой toolbar :
Здесь у нас находится только один элемент: кнопка поиска, которая должна перенаправлять нас на экран для поиска других пользователей.
В ранних версиях Android использовался элемент ActionBar , теперь же его функцию выполняет Toolbar . Важно, использовать Toolbar из пакета android.support.v7.widget , чтобы у нас была совместимость со старыми устройствами (версия Android ниже 5.0).
Поэтому сперва нам необходимо позаботиться о том, чтобы наши экраны не содержали элемент ActionBar по умолчанию. Для этого нам нужно унаследовать главный стиль приложения (находится в файле styles.xml ) от необходимого нам Theme.AppCompat.Light.NoActionBar :
resources> Base application theme. --> style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> Customize your theme here. --> item name="colorPrimary">@color/colorPrimaryitem> item name="colorPrimaryDark">@color/colorPrimaryDarkitem> item name="colorAccent">@color/colorAccentitem> style> Остальные элементы ниже не изменились --> resources>
Теперь необходимо добавить элемент Toolbar в xml -файл activity_user_info.xml . Для этого добавим Toolbar над контейнером RelativeLayout , в котором находится вся информация о пользователе. Также добавим стиль для тулбара, чтобы переиспользовать его на других экранах.
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> Весь контент информации о пользователе --> RelativeLayout> LinearLayout>
resources> Остальные элементы выше не изменились --> style name="Toolbar"> item name="android:layout_width">match_parentitem> item name="android:layout_height">?attr/actionBarSizeitem>- @style/ThemeOverlay.AppCompat.Dark.ActionBar
--> item name="android:background">@color/colorPrimaryitem> style> Остальные элементы ниже не изменились --> resources>
Атрибуты элемента Toolbar
Остановимся на некоторых атрибутах:
- «android:layout_height»>?attr/actionBarSize . Здесь мы указываем высоту тулбара. Таким синтаксисом мы можем получить доступ к значению высоты, которая применяется в атрибутах темы. По умолчанию, если мы не переопределяем значение, оно берётся из системного пакета темы support . Это значение лучше использовать, т.к. оно соответствует гайдам дизайна от Google . Подробнее можете изучить на сайте официальной документации.
- theme>@style/ThemeOverlay.AppCompat.Dark.ActionBar . Мы пока закомментировали этот атрибут. Объясним его чуть позже более наглядно.
Таким образом, мы добавили в нашу Activity тулбар. Но этого мало. Нам нужно сообщить ей, что мы используем его в качестве замены элемента ActionBar . Это необходимо, чтобы на устройствах со старой версией Android (ниже Android 5.0 (API 21)) наш интерфейс выглядел также, как и на устройства с новой версией. Для этого нам просто нужно вызвать метод Activity setSupportActionBar(Toolbar toolbar) :
public class UserInfoActivity extends AppCompatActivity < // Остальной код выше не изменился private Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) < // Остальной код выше не изменился toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); // Остальной код ниже не изменился > >
Важно, чтобы импорт вашего тулбара выглядел так: import android.support.v7.widget.Toolbar; . Именно тулбар из этого пакета нам и нужен.
Давайте запустим приложение и посмотрим, что получилось:
Видим, что текст в нашем тулбаре отображается тёмным цветом. Это потому что наше приложение по умолчанию использует Light тему Theme.AppCompat.Light.NoActionBar . Эта тема означает, что фоновый цвет будет светлым, а текст – тёмным.
Давайте раскомментируем атрибут тулбара, который указывает, что все его вложенные элементы должны использовать тему Dark . В тёмной теме весь текст будет отображать светлым цветом, а фоновый цвет – тёмным. Помним, что фоновый цвет тулбара мы тоже переопределяем, используя атрибут android:background .
resources> Остальные элементы выше не изменились --> style name="Toolbar"> item name="android:layout_width">match_parentitem> item name="android:layout_height">?attr/actionBarSizeitem> item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBaritem> item name="android:background">@color/colorPrimaryitem> style> Остальные элементы ниже не изменились --> resources>
Запустим приложение, посмотрим, что получилось:
Отлично, двигаемся дальше.
Осталось наполнить наш toolbar содержимым. Т.к. нашему тулбару необходима всего одна кнопка поиска, то мы можем обойтись стандартным способом добавления элементов в тулбар: при помощи Menu (помимо примера ниже также можете ознакомиться с данным уроком).
Скачивание png иконки
Давайте вначале скачаем иконку поиска, которая будет отображаться в menu . Как правило, для создания приложения достаточно пользоваться ресурсами, которые уже для разработчиков подготовил Google. Например, такая ситуация с иконками, которые рекомендует использовать Google. Их можно найти на этом сайте. В данном случае нам необходима иконка поиска, поэтому попробуем её найти, введя в поле поиска search :
Нашли подходящую иконку, выбрали в выпадающем списке тип Android и цвет, а теперь можем скачать .png -файлы. В первую очередь извлекаем архив для удобной работы с файлами. После извлечения архива видим, что в папке res содержится иконка промасштабированная для различных разрешений экранов, поэтому в зависимости от разрешения экрана устройство самостоятельно будет использовать наиболее подходящий ресурс для отображения.
Наша задача – обеспечить приложение иконками для разных разрешений. Подробнее об этом можно почитать в официальной документации.
Таким образом выделяем все папки внутри res ( drawable-hdpi , drawable-xhdpi и т.д.), копируем их, потом заходим в проект и вставляем их в папку res нашего приложения. После добавления иконок структура проекта выглядит так:
Т.е. мы скопировали несколько иконок для разных размеров экранов.
Если поменяем тип отображения файлов с Android на Project , то увидим, что физически создалось несколько папок, в каждой из которых лежит png для разного разрешения экрана.
Создание menu
Как мы с вами помним, для создания папки ресурсов menu необходимо нажать правой кнопкой по папке res и выбрать New -> Android resource directory . В появившемся диалоговом окне выбираем Resource type – menu . Все остальные поля заполнятся автоматически такими же значениями:
Нажимаем OK и видим, что папка создалась.
Затем создадим новый файл меню. Для этого правой кнопкой кликаем по папке menu и выбираем варианты New -> Menu resource file . Вводим имя user_info_menu.xml :
xml version="1.0" encoding="utf-8"?> menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> item android:id="@+id/action_search" app:showAsAction="always" android:icon="@drawable/ic_search_white_24dp" android:title="@string/search_hint"/> menu>
Из данного xml -файла можно увидеть, что наша иконка поиска будет всегда видна пользователю ( app:showAsAction=»always» ). Видим, что мы ссылаемся на иконку, которую только что добавили в проект ( android:icon=»@drawable/ic_search_white_24dp» ).
Теперь мы можем наполнить содержимым наш Toolbar , переопределив метод onCreateOptionsMenu в Activity . Это стало возможным благодаря тому, что мы вызвали метод setSupportActionBar(toolbar) .
Чтобы переопределить какой-то из методов мы можем нажать комбинацию клавиш Ctrl + O . После этого появится окно со всеми методами. Мы можем ввести название метода onCreateOptionsMenu . И выбрать его:
Давайте добавим в метод использование user_info_menu :
public class UserInfoActivity extends AppCompatActivity < // Остальной код выше не изменился @Override public boolean onCreateOptionsMenu(Menu menu) < getMenuInflater().inflate(R.menu.user_info_menu, menu); return true; > // Остальной код ниже не изменился >
Отлично, дело за малым: выполнить необходимое нам действие по клику на кнопку – перейти на экран для поиска пользователей:
public class UserInfoActivity extends AppCompatActivity < // Остальной код выше не изменился @Override public boolean onOptionsItemSelected(MenuItem item) < if(item.getItemId() == R.id.action_search) < Intent intent = new Intent(this, SearchUsersActivity.class); startActivity(intent); > return true; > // Остальной код ниже не изменился >
Единственная вещь, о которой ещё стоит упомянуть – это установка заголовка нашего экрана, отображающегося в тулбаре. Мы хотим устанавливать имя пользователя динамически в методе displayUserInfo . Для этого достаточно вызвать в необходимом месте метод тулбара setTitle(CharSequence title) . Помните, что мы вызывали строку setSupportActionBar(toolbar) . Также в Activity есть метод getSupportActionBar , который используется для совместимости со старыми устройствами. Его мы и будем использовать. Давайте добавим эту логику в метод displayUserInfo() :
public class UserInfoActivity extends AppCompatActivity < private void displayUserInfo(User user) < // остальной код выше не изменился getSupportActionBar().setTitle(user.getName()); > >
AndroidStudio может подчёркивать вызов getSupportActionBar().setTitle , сообщая, что объект может быть null . Но мы помним, что мы вызвали метод setSupportActionBar(toolbar) , поэтому можем пока игнорировать это замечание.
Запустим приложение и посмотрим на результат:
В результате данного урока мы узнали:
- что такое элемент Toolbar ;
- что такое Menu и как его использловать с элементом Toolbar ;
- каким образом наполнить Toolbar пользовательскими элементами.
- Русскоязычные:
- Material Design. Динамический Toolbar на живом примере
- Официальная документация. Поддержка экранов с различной плотностью пикселей
- Создание меню
- Официальная документация. Меню
- Официальная документация. Toolbar
- Официальная документация. Работа с toolbar
Полный листинг изменений кода:
Убрать toolbar в Andorid Studio 2.2.2
Добрый вечер. Обновился до версии 2.2.2. При создании нового проекта выбираю «Basic Activity». Открывается. Дальше откуда не возьмись появляется сверху Toolbar, код которого не пойму откуда берется. Как его убрать? Хочу сделать стартовую страницу с заставкой при загрузке приложения. В более ранних версия, например 1.4 такого не было. Спасибо!
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:Как убрать toolBar по умолчанию?
Привет. При создании пустого проекта, на форме автоматиччески уже создан toolBar. Как его убрать?Как убрать весь toolbar при запуске своего XLS файла?
как убрать весь toolbar при запуске своего XLS файла? Application.CommandBars(»).Visible = False.Toolbar как установить свои, созданые в редакторе ресурсов visual studio битмапы на кнопки?
На сайте MSDN есть пример создания toolbar. Там для кнопок используют стандартные изображения.Andorid приложения
Какую посоветуйте литературу для того чтобы писать простые приложение для Андроид. К примеру.ActionBar (Панель действий)
Начиная с Android 3.0 (API 11), в приложениях появилась возможность использовать панель действий ActionBar, которая сочетает в себе заголовок и меню, упрощая навигацию и предоставляя быстрый доступ к частым операциям.
ActionBar заменяет Options Menu, которое было в ранних версиях Android, используя новые дополнительные параметры для меню. По умолчанию, новые проекты, создаваемые через шаблоны Empty Activity и др., уже содержат ActionBar. Следует отметить, что в Android 5.0 появился новый компонент Toolbar, который является дальнейшим развитием ActionBar. И он активно вытесняет панель действий. Но вам всё равно следует изучить работу ActionBar, так как основные принципы работы завязаны на ней.
Если запустить программу как есть из шаблона Empty Activity, то увидим заголовок программы.
Если в код программы добавить методы для меню, то справа появится значок из трёх вертикальных точек.
Если щёлкнуть по значку из трёх точек, выстроенных по вертикали, то увидим всплывающее меню с единственным пунктом Settings. Не прикладывая никаких усилий, мы получили готовый элемент ActionBar в своём приложении.
Давайте разбираться, что происходит за кулисами приложения. За появление панели действий отвечает тема Theme.Holo или её производные. В API 21 и выше произошли небольшие изменения. Как я уже сказал выше, появился новый компонент ToolBar, который может заменить панель действий в активности. Поэтому тут нужно быть внимательным и выбирать соответствующую тему, например, Theme.Material.Light.DarkActionBar. Для старых устройств используются библиотеки совместимости. В этом случае активность наследуется от AppCompatActivity, а используемая тема Theme.AppCompat или его производные, например, Theme.AppCompat.Light.DarkActionBar.
В студии версии 4.1 снова всё поменяли и теперь используется тема Theme.MaterialComponents.DayNight.DarkActionBar.
Прячем и показываем ActionBar
Изначально существовали два вида ActionBar для новых устройств и для старых устройств при помощи библиотеки совместимости. Не смешивайте вызовы методов из разных классов, а то получите ошибку. На сегодняшний день студия создаёт проекты с применением библиотеки AndroidX, поэтому будем использовать классы из неё.
Чтобы увидеть разницу в активности с ActionBar и без неё, напишем простой пример. Добавим на форму компонент ToggleButton и пропишем код, скрывающий и показывающий ActionBar:
Вы вошли на сайт, как гость.
Необходимо зарегистрироваться, чтобы прочитать статьюИспользование Spinner в Android
Компонент Spinner предоставляет быстрый способ выбора значения из предложенного списка с вариантами. Поскольку список выводится только при нажатии на спиннер, это экономит место на экране вашего устройства. В состоянии по умолчанию спиннер отображает текущее значение. Если же коснуться компонента, то появится выпадающее меню со всеми другими доступными значениями, из которых пользователь может выбрать нужное ему.
Например, когда вы пользуетесь галереей на своём устройстве, вы используете спиннер, чтобы выбрать, какую категорию или папку нужно отобразить.
Создадим свой собственный спиннер со своей разметкой. Он будет содержать список стран с флагами. Для начала создадим в Android Studio новый проект, внутри которого в файл activity_main.xml поместим следующий код:
Затем добавим вспомогательный класс CountyInfo, с помощью которого будем заполнять спиннер данными.
В данном случае нам будут нужны:
- Название страны;
- Флаг;
- Численность населения.
В списке будут отображаться только флаг и название страны, затем при выборе в отдельном TextView будет выведена полная информация вместе с численностью населения. Данные захардкожены, однако если есть желание, можно добавить возможность вводить данные вручную пользователям.
public class CountryInfo < private String countryName; private long countryPopulation; private int countryFlag; public CountryInfo(String cName, long cPopulation, int flagImage) < countryName = cName; countryPopulation = cPopulation; countryFlag = flagImage; >public String getCountryName() < return countryName; >public long getCountryPopulation() < return countryPopulation; >public int getCountryFlag() < return countryFlag; >public String toString() < return countryName; >>
Кроме того, нам нужен адаптер, в котором записи будут храниться. Для этого создадим класс CountryAdapter, наследующий ArrayAdapter со следующим кодом:
public class CountryAdapter extends ArrayAdapter < private Activity context; ArrayListdata = null; public CountryAdapter(Activity context, int resource, ArrayList data) < super(context, resource, data); this.context = context; this.data = data; >@Override @NonNull public View getView(int position, View convertView, @NonNull ViewGroup parent) < return super.getView(position, convertView, parent); >@Override public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) < // этот код выполняется, когда вы нажимаете на спиннер View row = convertView; if (row == null) < LayoutInflater inflater = context.getLayoutInflater(); row = inflater.inflate(R.layout.spinner_layout, parent, false); >CountryInfo item = data.get(position); if (item != null) < // парсим данные с каждого объекта ImageView myFlag = (ImageView) row.findViewById(R.id.imageIcon); TextView myCountry = (TextView) row.findViewById(R.id.countryName); if (myFlag != null) < myFlag.setBackground(context.getResources().getDrawable(item.getCountryFlag(), context.getTheme())); >if (myCountry != null) myCountry.setText(item.getCountryName()); > return row; > >
В методе getDropDownView() создаётся собственный макет для установки нужных ImageView и TextView.
В классе главной активности добавим следующий код, который будет реализовывать наш спиннер. Предварительно нужно найти флаги стран и добавить их в папку drawable нашего проекта.
Spinner mySpinner; TextView myTextView; ArrayList myCountries; @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); myCountries = populateList(); setContentView(R.layout.activity_main); mySpinner = (Spinner) findViewById(R.id.SpinnerCustom); myTextView = (TextView) findViewById(R.id.myTextView); CountryAdapter myAdapter = new CountryAdapter(this, android.R.layout.simple_spinner_item, myCountries); mySpinner.setAdapter(myAdapter); mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() < @Override public void onItemSelected(AdapterViewadapterView, View view, int i, long l) < CountryInfo myCountry; if (mySpinner.getSelectedItem() != null) < myCountry = (CountryInfo) mySpinner.getSelectedItem(); myTextView.setText(String.format("Страна: " + myCountry.getCountryName() + "\nЧисленность населения: " + myCountry.getCountryPopulation())); >> @Override public void onNothingSelected(AdapterView adapterView) < >>); > public ArrayList populateList() < ArrayListmyCountries = new ArrayList(); myCountries.add(new CountryInfo("США", 308745538, R.drawable.usa)); myCountries.add(new CountryInfo("Россия", 9482855, R.drawable.russia)); myCountries.add(new CountryInfo("Канада", 34018000, R.drawable.canada)); return myCountries; >
Метод populateList() используется для того, чтобы заполнить наш спиннер данными о странах.
Теперь нужно добавить разметку для будущего спиннера. Чтобы это сделать, нужно в layout добавить файл spinner_layout.xml со следующим кодом:
У элемента LinearLayout в свойстве background указан ресурс drawable, он используется для того, чтобы задать градиент для спиннера. Создадим файл bluegradient.xml в папке drawable со следующим кодом:
В результате всех проделанных манипуляций мы получили красивый раскрывающийся список со странами.
Кроме того, при изменении выбранного элемента в списке, происходит обновление текстового поля.
У компонента Spinner в Android существуют два способа отображения, которые можно задать в файле разметки:
В примере выше был показан первый вариант, когда спиннер отображается в приложении в виде выпадающего списка. Теперь модифицируем приложение, чтобы список выводился в диалоговом окне. Для этого в файле activity_main.xml в тэге допишем новое свойство:
android:spinnerMode="dialog"
Данное свойство изменит способ отображения спиннера. По умолчанию, значение spinnerMode равно dropdown. Посмотрим, как изменился наш спинер.
Поскольку Spinner можно разместить в любом месте в приложении, это также можно сделать и в тулбаре (Toolbar), как вы, возможно, видели в приложениях Галерея и Gmail на своём устройстве. Для этого вставим в activity_main.xml следующий код перед :
Таким образом мы объявили свой собственный тулбар и разместили на нём ещё один спиннер. Теперь нужно убрать тулбар, предоставляемый темой приложения, для этого зайдём в файл styles.xml и изменим значение parent у нашей темы. В итоге должно получится примерно следующее:
Теперь в классе активности добавим тулбар и спиннер, и установим ему адаптер. Для этого объявим их:
Spinner navSpinner; Toolbar toolbar;
Затем инициализируем после метода setContentView() в onCreate():
navSpinner = (Spinner) findViewById(R.id.SpinnerNav); toolbar = (Toolbar) findViewById(R.id.toolbar);
В заключение после mySpinner.setAdapter(myAdapter); установим адаптер и второму спиннеру:
navSpinner.setAdapter(myAdapter);
Теперь мы можем запустить наше приложение и убедиться, что на тулбаре заместо названия приложения теперь находится созданный спиннер. При желании ему также можно назначить OnItemSelectedListener, который будет менять текст на активности при смене значения.