- PVSM.RU - https://www.pvsm.ru -
В данной статье я расскажу, как быстро добавить в ваше приложение для Android боковое меню (aka Navigation Drawer) в стиле Material Design. Для этого мы воспользуемся библиотекой [1], любезно предоставленной Mike Penz [2].
У вас получится Navigation Drawer, который:
Помимо этого, новички обучатся интеграции сторонних библиотек в свой проект, что крайне полезно, учитывая их грандиозное разнообразие на Github.
В примере будет использоваться интегрированная среда разработки Android Studio от компании Google, основанная на IntelliJ IDEA, которую сама корпорация активно продвигает. Все действия можно воспроизвести используя и другие среды, например, Eclipse. Однако статья ориентирована на новичков, а они будут в большинстве своем использовать именно Android Studio, так как именно его Google теперь и предлагает при скачивании Android SDK с developer.android.com [3] (ранее можно было скачать Eclipse).
Итак, выбираем в меню «File» -> «New Project...»:
Заполняем имя приложения, пакета, выбираем SDK.
Создавать проект мы будем с поддержкой минимального API Level равного 14, что соответствует Android 4.0 Ice Cream Sandwich, поскольку всё, что ниже, составляет менее 8% аудитории и привносит несоизмеримо большее количество головной боли:
В последних двух окнах оставляем все по умолчанию, жмем «Finish».
Для того, чтобы красивый Navigation Drawer работал на версиях Android ниже 5.0 и выглядел в стиле Material Design, необходимо включить в проект библиотеку поддержки от Google, которая носит название v7 appcompat library [4]. В текущей версии Android Studio (1.0.2) библиотека подключается по умолчанию при создании проекта. Проверьте это в файле проекта appbuild.gradle, в разделе dependencies должна быть строка (цифры могут быть не обязательно «21.0.3»):
compile 'com.android.support:appcompat-v7:21.0.3'
а класс MainActivity должен наследоваться от ActionBarActivity
public class MainActivity extends ActionBarActivity {
Также проверьте в resvaluesstyles.xml, чтобы тема приложения наследовалась от Theme.AppCompat или ее вариаций без ActionBar (мы заменим ActionBar на ToolBar), например:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
Добавьте в раздел dependencies файла appbuild.gradle строки
compile('com.mikepenz.materialdrawer:library:0.9.5@aar') {
transitive = true
}
и нажмите появившуюся в верхней части окна кнопку «Sync Now» для синхронизации вашего проекта.
В главный layout приложения нужно добавить ToolBar. Приведите activity_main.xml к такому виду:
<RelativeLayout 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=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:paddingTop="@dimen/tool_bar_top_padding"
android:transitionName="actionBar" />
</RelativeLayout>
Создайте в папке layout файл drawer_header.xml со следующим содержанием
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:orientation="vertical"
android:scaleType="fitCenter"
android:src="@drawable/header"></ImageView>
этот файл — разметка для верхней части Drawer'a, в которой находится картинка. Теперь положите в папку resdrawable любую картинку с именем header.jpg, которая будет отображаться в верхней части Drawer'a, например эту:
Файл resstrings.xml, содержащий строковые ресурсы, приведите к следующему виду
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
<string name="action_settings">Settings</string>
<string name="drawer_item_home">Home</string>
<string name="drawer_item_free_play">Free Play</string>
<string name="drawer_item_custom">Custom</string>
<string name="drawer_item_settings">Settings</string>
<string name="drawer_item_help">Help</string>
<string name="drawer_item_open_source">Open Source</string>
<string name="drawer_item_contact">Contact</string>
</resources>
В методе onCreate вашей MainActivity мы инициализируем ToolBar, добавьте после setContentView следующий код:
// Handle Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Затем инициализируем и сам Navigation Drawer, добавьте ниже:
new Drawer()
.withActivity(this)
.withToolbar(toolbar)
.withActionBarDrawerToggle(true)
.withHeader(R.layout.drawer_header)
.addDrawerItems(
new PrimaryDrawerItem().withName(R.string.drawer_item_home).withIcon(FontAwesome.Icon.faw_home).withBadge("99").withIdentifier(1),
new PrimaryDrawerItem().withName(R.string.drawer_item_free_play).withIcon(FontAwesome.Icon.faw_gamepad),
new PrimaryDrawerItem().withName(R.string.drawer_item_custom).withIcon(FontAwesome.Icon.faw_eye).withBadge("6").withIdentifier(2),
new SectionDrawerItem().withName(R.string.drawer_item_settings),
new SecondaryDrawerItem().withName(R.string.drawer_item_help).withIcon(FontAwesome.Icon.faw_cog),
new SecondaryDrawerItem().withName(R.string.drawer_item_open_source).withIcon(FontAwesome.Icon.faw_question).setEnabled(false),
new DividerDrawerItem(),
new SecondaryDrawerItem().withName(R.string.drawer_item_contact).withIcon(FontAwesome.Icon.faw_github).withBadge("12+").withIdentifier(1)
)
.build();
В случае появления ошибок, убедитесь, что ваша секция импортов в MainActivity выглядит так:
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import com.mikepenz.iconics.typeface.FontAwesome;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
import com.mikepenz.materialdrawer.model.SectionDrawerItem;
Теперь можно запустить приложение и оценить результат:
Чтобы Navigation Drawer еще точнее соответствовал рекомендациям от Google, можно сделать следующие улучшения (см. полный листинг MainActivity в конце статьи):
.withOnDrawerListener(new Drawer.OnDrawerListener() {
@Override
public void onDrawerOpened(View drawerView) {
InputMethodManager inputMethodManager = (InputMethodManager) MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0);
}
@Override
public void onDrawerClosed(View drawerView) {
}
})
@Override
public void onBackPressed(){
if(drawerResult.isDrawerOpen()){
drawerResult.closeDrawer();
}
else{
super.onBackPressed();
}
}
Реализацию всех этих улучшений вы можете посмотреть в полном листинге MainActivity:
package ru.sample.drawer.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.Toast;
import com.mikepenz.iconics.typeface.FontAwesome;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
import com.mikepenz.materialdrawer.model.SectionDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.Badgeable;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.Nameable;
public class MainActivity extends ActionBarActivity {
private Drawer.Result drawerResult = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Инициализируем Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Инициализируем Navigation Drawer
drawerResult = new Drawer()
.withActivity(this)
.withToolbar(toolbar)
.withActionBarDrawerToggle(true)
.withHeader(R.layout.drawer_header)
.addDrawerItems(
new PrimaryDrawerItem().withName(R.string.drawer_item_home).withIcon(FontAwesome.Icon.faw_home).withBadge("99").withIdentifier(1),
new PrimaryDrawerItem().withName(R.string.drawer_item_free_play).withIcon(FontAwesome.Icon.faw_gamepad),
new PrimaryDrawerItem().withName(R.string.drawer_item_custom).withIcon(FontAwesome.Icon.faw_eye).withBadge("6").withIdentifier(2),
new SectionDrawerItem().withName(R.string.drawer_item_settings),
new SecondaryDrawerItem().withName(R.string.drawer_item_help).withIcon(FontAwesome.Icon.faw_cog),
new SecondaryDrawerItem().withName(R.string.drawer_item_open_source).withIcon(FontAwesome.Icon.faw_question).setEnabled(false),
new DividerDrawerItem(),
new SecondaryDrawerItem().withName(R.string.drawer_item_contact).withIcon(FontAwesome.Icon.faw_github).withBadge("12+").withIdentifier(1)
)
.withOnDrawerListener(new Drawer.OnDrawerListener() {
@Override
public void onDrawerOpened(View drawerView) {
// Скрываем клавиатуру при открытии Navigation Drawer
InputMethodManager inputMethodManager = (InputMethodManager) MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0);
}
@Override
public void onDrawerClosed(View drawerView) {
}
})
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
@Override
// Обработка клика
public void onItemClick(AdapterView<?> parent, View view, int position, long id, IDrawerItem drawerItem) {
if (drawerItem instanceof Nameable) {
Toast.makeText(MainActivity.this, MainActivity.this.getString(((Nameable) drawerItem).getNameRes()), Toast.LENGTH_SHORT).show();
}
if (drawerItem instanceof Badgeable) {
Badgeable badgeable = (Badgeable) drawerItem;
if (badgeable.getBadge() != null) {
// учтите, не делайте так, если ваш бейдж содержит символ "+"
try {
int badge = Integer.valueOf(badgeable.getBadge());
if (badge > 0) {
drawerResult.updateBadge(String.valueOf(badge - 1), position);
}
} catch (Exception e) {
Log.d("test", "Не нажимайте на бейдж, содержащий плюс! :)");
}
}
}
}
})
.withOnDrawerItemLongClickListener(new Drawer.OnDrawerItemLongClickListener() {
@Override
// Обработка длинного клика, например, только для SecondaryDrawerItem
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id, IDrawerItem drawerItem) {
if (drawerItem instanceof SecondaryDrawerItem) {
Toast.makeText(MainActivity.this, MainActivity.this.getString(((SecondaryDrawerItem) drawerItem).getNameRes()), Toast.LENGTH_SHORT).show();
}
return false;
}
})
.build();
}
@Override
public void onBackPressed() {
// Закрываем Navigation Drawer по нажатию системной кнопки "Назад" если он открыт
if (drawerResult.isDrawerOpen()) {
drawerResult.closeDrawer();
} else {
super.onBackPressed();
}
}
// Заглушка, работа с меню
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
// Заглушка, работа с меню
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Готовый пример из статьи на Github: https://github.com/tral/MaterialDrawerSample [5];
Библиотека MaterialDrawer от Mike Penz: https://github.com/mikepenz/MaterialDrawer [1]
Google Material Design Guidelines: Navigation Drawer: http://www.google.com/design/spec/patterns/navigation-drawer.html [6];
Dashboards: https://developer.android.com/about/dashboards/index.html?utm_source=ausdroid.net [7];
Support Library: https://developer.android.com/tools/support-library/index.html [8]
Автор: tralchonok
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/83141
Ссылки в тексте:
[1] библиотекой: https://github.com/mikepenz/MaterialDrawer
[2] Mike Penz: http://portfolio.mikepenz.com/
[3] developer.android.com: http://developer.android.com/sdk/index.html
[4] v7 appcompat library: http://developer.android.com/tools/support-library/features.html#v7-appcompat
[5] https://github.com/tral/MaterialDrawerSample: https://github.com/tral/MaterialDrawerSample
[6] http://www.google.com/design/spec/patterns/navigation-drawer.html: http://www.google.com/design/spec/patterns/navigation-drawer.html
[7] https://developer.android.com/about/dashboards/index.html?utm_source=ausdroid.net: https://developer.android.com/about/dashboards/index.html?utm_source=ausdroid.net
[8] https://developer.android.com/tools/support-library/index.html: https://developer.android.com/tools/support-library/index.html
[9] Источник: http://habrahabr.ru/post/250765/
Нажмите здесь для печати.