Pull to refresh

Реализация выдвижного меню NavigationDrawer при помощи DrawerLayout, с использованием произвольной разметки

Reading time 4 min
Views 18K
На днях для одного из разрабатываемого нашей командой приложения, заказчик внес правку в дизайн, которая требовала разработать выдвижное меню с довольно не стандартным расположением view компонентов. Хотя на данный момент и существуют различные виды реализации данной задачи, они оказывались либо слишком объемными, либо не предоставляли реализацию нужного функционала.

Обдумав некоторое время данную задачу, я решил реализовать данное меню на основе стандартного компонента DrawerLayout, в основу которого было вложено 2 root элемента — RelativeLayout для основной разметки окна, а также еще один RelativeLayout как контейнер для бокового меню. Хотелось бы добавить, что именно 2 root элемента должно быть внутри DrawerLayout, подробнее об этом контейнере можно прочесть в официальной документации гугла.

Реализация


Xml файл разметки для основной activity


<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

       <!-- Основной контейнер разметки -->
     
    </RelativeLayout>

    <!-- Контейнер, содержащий выдвижное меню -->
    <RelativeLayout
        android:id="@+id/left_drawer"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="none"
        <!-- обязательно добавляем данный атрибут, иначе все, что находится под выдвинутым 
               меню будет кликабельно, даже если нажимать на элементы самого меню -->
        android:clickable="true"
        android:background="#FFFFFF"
        xmlns:android="http://schemas.android.com/apk/res/android" />

</android.support.v4.widget.DrawerLayout>

Разметка основной activity готова, теперь приступим к написанию класса, который будет выполнять основную логику. Создадим класс, наследующий RelativeLayout. Данный класс реализует всю логику нашего меню, в том числе устанавливает разметку и определяет все view.

public class NavigationLayout extends RelativeLayout
{
    Button ok;
    public NavigationLayout(Context context,RelativeLayout parent)
    {
        super(context);
        initView(context,parent);
    }

    public void initView(final Context context,RelativeLayout parent)
    {
        // надуваем любой xml файл разметки
        View view= LayoutInflater.from(context).inflate(R.layout.view_drawer_layout,parent,true);

        ok=(Button)view.findViewById(R.id.ok);

        ok.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context,"Ok",Toast.LENGTH_SHORT).show();
            }
        });


    }
}

В конструктор следует передать context и parent.

parent — RelativeLayout, который был объявлен в разметке для основной activity ( )

Далее функция initView(final Context context,RelativeLayout parent) — надувает основную разметку, которая будет помещена в выдвижное меню, а также определим тут все view компоненты и их слушатели.

В R.layout.view_drawer_layout для примера я объявил всего одну кнопку.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="300dp"
    android:background="@color/screen_background"
    android:layout_height="match_parent">

    <Button
        android:layout_width="110dp"
        android:layout_height="55dp"
        android:textAllCaps="false"
        android:id="@+id/ok"
        android:text="Next"
        android:textStyle="bold"
        android:textSize="25sp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textColor="@color/buttonTextColor" />

</RelativeLayout>

На данном этапе основная часть готова, осталось лишь добавить наш NavigationLayout при помощи addView к основному parent контейнеру.

Создадим класс, наследующий AppCompactActivity

public class ParentNavigationActivity extends AppCompatActivity {
    NavigationLayout navigationLayout;
    RelativeLayout left_drawer;

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        super.setContentView(layoutResID);
        setupMenu();
    }

    public void setupMenu()
    {
        left_drawer=(RelativeLayout) findViewById(R.id.left_drawer);
        navigationLayout=new NavigationLayout(getApplicationContext(),left_drawer);

        left_drawer.addView(navigationLayout);
    }
}

Данный класс переопределяет стандартный метод setContentView, добавляя в него вызов функции, которая 'инициализирует' выдвижное меню. Также здесь мы создаем объект ранее написанного нами NavigationLayout класса и добавляем его при помощи left_drawer.addView(navigationLayout) к родителю, который и является контейнером бокового меню.

Осталось дело за малым — чтобы все заработало, нужно лишь создать экран (activity) и унаследовать ParentNavigationActivity, который мы только что создали.

public class MainActivity extends ParentNavigationActivity {

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

}

Таким образом, при наследовании ParentNavigationActivity и вызове функции setContentView, в нашей activity появляется готовое меню.



Хотелось бы добавить, что 2 контейнера, лежащих в основе DrawerLayout, необязательно должны быть RelativeLayout. Вместо них можно использовать constraintlayout, framelayout, linearlayout и другие.

На данном этапе разработка выдвижного меню завершена!


Данный способ является довольно простым в реализации, а также гибким в плане добавления меню к любым activity. Надеюсь что данная статья поможет android разработчикам упростить создание бокового меню для своих приложений.
Tags:
Hubs:
+9
Comments 10
Comments Comments 10

Articles