На днях, для одного из разрабатываемого нашей командой приложения, заказчик внес правку в дизайн, которая требовала разработать выдвижное меню с довольно не стандартным расположением 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 разработчикам упростить создание бокового меню для своих приложений.
Автор: AlexandrGritsenko