geektimes

Иконка бокового меню из Material Design (как в Google Play)

  • среда, 5 ноября 2014 г. в 02:10:32
http://habrahabr.ru/post/242033/

Привет, Хабражители!

Наверное, многие заметили, что в последних версиях приложений Google Play и Google+ Фото для Android иконка бокового меню (NavigationDrawer) имеет красивую анимацию (переход из трёх полосок в стрелку). Пример здесь. Мне стало интересно, как это реализовано, и я отправился в путешествие по просторам Всемирной паутины в поисках ответа на этот вопрос. Теперь же спешу поделиться с вами этим рецептом.

Кому интересно, прошу под кат.


Сразу перейдём к созданию проекта. Сначала я хотел назвать его ActionBarDrawerToggleWithAnimationFromGooglePlayDemo, но потом передумал.
Итак, проект называется AnimatedDrawerToggleDemo. Обязательное условие — минимальный SDK должен быть 7 или выше, потому что компоненты находятся в библиотеке v7 AppCompat.
Я старался сделать пример как можно проще, поэтому убрал всё лишнее: даже по нажатию на элемент NavigationDrawer ничего не происходит.

Сначала создадим в файле res/values/strings.xml строки:

    <string name="navigation_drawer_open">Open navigation drawer</string>
    <string name="navigation_drawer_close">Close navigation drawer</string>


Для того, чтобы реализовать нужный нам эффект, мы будем использовать вместо ActionBar новый компонент Toolbar. Для этого нужно отключить отображение самого ActionBar, я это сделал в теме программы (res/values/styles.xml):
<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        
    </style>
</resources>

Тема для всех API должна наследоваться от Theme.AppCompat.NoActionBar или Theme.AppCompat.Light.NoActionBar, поэтому также внесите изменения в файлы res/values-xx/styles.xml, если они у вас есть.
Более подробно о Toolbar можно почитать здесь. Кстати, спасибо автору перевода.

Создадим файл разметки res/layout/activity_main:
<LinearLayout 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"
    android:orientation="vertical" >
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        theme="@style/ThemeOverlay.AppCompat.ActionBar" />
    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <ListView
            android:id="@+id/lv_navigation_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/white" />
    </android.support.v4.widget.DrawerLayout>
</LinearLayout>


Здесь мы объявляем Toolbar и NavigationDrawer, в котором находятся FrameLayout (для фрагмента, которого у нас нет) и ListView (боковое меню).

Наконец-то перейдём к самому интересному — коду программы. Файл src/com.ed.animated_drawer_toggle_demo/MainActivity:
package com.ed.animated_drawer_toggle_demo;

import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends ActionBarActivity {

	private ActionBarDrawerToggle toggle;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
		setSupportActionBar(toolbar);
        
		DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		toggle = new ActionBarDrawerToggle(
        		this, 
        		drawerLayout, 
        		R.string.navigation_drawer_open, 
        		R.string.navigation_drawer_close);
		toggle.setDrawerIndicatorEnabled(true);
		drawerLayout.setDrawerListener(toggle);
        
		ListView lv_navigation_drawer = (ListView) findViewById(R.id.lv_navigation_drawer);
		lv_navigation_drawer.setAdapter(new ArrayAdapter<String>(
        		this, 
        		android.R.layout.simple_list_item_1, 
        		new String[] {"Screen 1", "Screen 2", "Screen 3"}));
 	}
    
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (toggle.onOptionsItemSelected(item))
			return true;
		return super.onOptionsItemSelected(item);
	}

	@Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        toggle.syncState();
    }
	
	@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        toggle.onConfigurationChanged(newConfig);
    }
}

Сначала мы инициализируем Toolbar и присваиваем его нашей Activity вместо ActionBar.
Затем находим ActionBarDrawerToggle и присваиваем его боковому меню. Вся красота (добавление анимации) описывается всего лишь одной строчкой кода — toggle.setDrawerIndicatorEnabled(true);.
После этого создаём простенькое меню, чтобы там хоть что-то было.
Последние три метода нужны для корректной работы ActionBarDrawerToggle.

Вот и всё! Приложение корректно работает на всех версиях:
Android 2.3



Android 4.1





P. S. идея и код нагло взяты отсюда.