본문 바로가기
안드로이드 스튜디오

[안드로이드 스튜디오] 앱만들기 #10. Navigation Menu 커스텀

by sojung118 2024. 9. 3.

[ 실행 화면 ] (WebViewExample은 무시.. 이전 강의 파일에서 그대로 변경해서 남아있는것)

activity_main.xml

activity_drawer.xml

 


 

 

벌써 #10까지 온 안드로이드 스튜디오 강의!

저번에는 안드로이드 스튜디오에서 기본으로 제공하는 Navigation 양식을 썼다면

이번에는 Empty 양식에 내가 직접 Navigation Menu를 만들고 커스텀해보는 강의였다.

바로 시작해보자 >,<

 


 

1. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@mipmap/odung" />

        <Button
            android:id="@+id/btn_open"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="열려라 참깨!"
            android:backgroundTint="#E6A1A1"/>

    </LinearLayout>
    <include layout = "@layout/activity_drawer"/>


</androidx.drawerlayout.widget.DrawerLayout>


<!--activity_drawer layout을 포함시켜라의 include-->
<!--즉 main.xml에서 activity_drawer을 연결시킨것-->

 

 

강의에서는 버튼만 만들어서 버튼을 클릭하면 drawer가 나오게 설정했는데,

이왕 넣는 김에 ImageView도 하나 넣고 싶어서 내가 임의로 오둥이 사진을 넣었다!

항상 LinearLayout으로 설정해주던 첫 부분을 DrawerLayout으로 설정해주고

DrawerLayout 안에 LinearLayout을 다시 넣어서 안에 여러 내용을 넣어줬다.

id, backgroundTint 등 색상이나 아이디 관련 부분은 임의로 바꿔주도록 하자.

 


 

2. activity_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:id="@+id/drawer"
    android:layout_gravity="start"
    android:orientation="vertical"
    android:background="#F8E7D8">
    
    <Button
        android:backgroundTint="#E6A1A1"
        android:id="@+id/btn_close"
        android:text="메뉴 닫기"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="안드로이드 메뉴"
        android:gravity="center"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#D7C692"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="테스트 메뉴"
            android:gravity="center"
            android:layout_margin="5dp"/>




    </LinearLayout>

</LinearLayout>


<!--실제 메뉴가 열렸을때를 상상하면서 만들기-->
<!--슬라이드 메뉴를 직접 만드는것-->
<!--alt+enter를 하면 오류에 대해서 추천해결방법을 알려줌-->

 

 

이 부분은 버튼을 클릭하거나 옆쪽으로 슬라이드를 했을때 나오는 drawer에 대한 xml이다.

실제 메뉴가 열렸을때를 상상하면서 만들면 더 디자인하기 쉬울듯?

이 xml의 가로 (width) 는 240dp로 설정해서 화면을 꽉 채우지 않도록 설정해줬다.

그리고 버튼이나 텍스트뷰를 넣으면서 안에 들어갈 내용을 채워줬다.

여기에서도 margin이나 background(Tint) 같은건 임의로 설정해주면 된다.

 

 

※ 이렇게 2가지 xml을 완성하고 나서 activity_main.xml에서

<include layout = "@layout/activity_drawer"/>

 

이 코드를 추가해준다.

이 코드는 말 그대로 activity_main.xml에 activity_drawer.xml을 포함시키겠다는 뜻이다.

즉 main.xml에서 drawer.xml을 연결시킨것이라고 보면 될 것 같다.

main.xml에서 버튼을 누르거나 슬라이드 할 때 drawer.xml이 나와야하니까!

 


 

 

3. MainActivity.java

package com.example.webviewexample;

import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;

import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.drawerlayout.widget.DrawerLayout;

public class MainActivity extends AppCompatActivity {

    //DrawerLayout과 View 2개를 만들어준다.

    private DrawerLayout drawerLayout;
    private View drawerView;

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


        drawerLayout = findViewById(R.id.drawer_layout);
        drawerView = findViewById(R.id.drawer);



        Button btn_open = findViewById(R.id.btn_open);
        btn_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawerLayout.openDrawer(drawerView);
            }
        });

        drawerLayout.setDrawerListener(listener);
        drawerView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });




        ////////////////////////////




        Button btn_close = findViewById(R.id.btn_close);
        btn_close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawerLayout.closeDrawers();
            }
        });

    }

    //drawerlayout을 왼쪽,오른쪽으로 슬라이드했을떄 이곳에서 상태값을 받아옴
    //추가 기능을 해주고싶을때 여기서 만들기
    DrawerLayout.DrawerListener listener = new DrawerLayout.DrawerListener() {
        @Override
        public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {

        }

        //오픈이 완료됐을때
        @Override
        public void onDrawerOpened(@NonNull View drawerView) {

        }

        //슬라이드 닫혔을때
        @Override
        public void onDrawerClosed(@NonNull View drawerView) {

        }

        //상태가 change 됐을때
        @Override
        public void onDrawerStateChanged(int newState) {

        }
    };


}

 

 

마지막으로 이벤트들을 설정해 줄 MainActivity.java 파일이다.

  • DrawerLayout, View 변수 설정해주기
  • 설정한 변수에 findViewById로 id 연결해주기
  • btn_open 버튼을 클릭했을때 일어나는 이벤트 설정하기 (openDrawer)
  • btn_close 버튼을 클릭했을때 일어나는 이벤트 설정하기 (closeDrawers)
  • drawerLayout.setDrawerListener(listener);
    • drawerLayout에 드로어 리스너(listener)를 설정
    • 이 리스너는 드로어의 상태 변화(열림, 닫힘, 슬라이드 등)를 감지함.
  • drawerView.setOnTouchListener(new View.OnTouchListener() { ... });
    • drawerView에 터치 리스너를 설정합니다.
    • 터치 이벤트를 항상 true로 반환하여, 해당 뷰가 터치 이벤트를 처리하도록 강제하고, 다른 이벤트 처리를 방지.
    • 이 설정은 드로어가 열려 있을 때 다른 UI 요소들이 드로어와의 상호작용을 하지 못하게 할 때 사용됨.
  • DrawerLayout.DrawerListener listener = new DrawerLayout.DrawerListener() { ... };
    • onDrawerSlide(@NonNull View drawerView, float slideOffset):
      • 드로어가 슬라이드 될 때 호출
      • slideOffset은 드로어가 얼마나 열렸는지를 나타내는 값 (0.0은 닫힘, 1.0은 완전히 열림).
    • onDrawerOpened(@NonNull View drawerView):
      • 드로어가 완전히 열렸을 때 호출.
      • 이 메서드는 드로어가 완전히 열렸을 때 특정 작업을 실행하고 싶을 때 유용.
    • onDrawerClosed(@NonNull View drawerView):
      • 드로어가 완전히 닫혔을 때 호출. 드로어가 닫힐 때 특정 작업을 처리하는 데 사용.
    • onDrawerStateChanged(int newState):
      • 드로어의 상태가 변경될 때 호출. 예를 들어, 드로어가 열리기 시작했는지, 닫히기 시작했는지, 아니면 사용자가 슬라이드하고 있는지 등을 감지할 수있음. newState는 드로어의 새로운 상태를 나타냄.

 


 

 

이렇게 코드를 짜면, main.xml에서 btn_open 버튼을 누르면 drawer 창이 열리고

drawer.xml에서 btn_close 버튼을 누르면 drawer 창이 닫힌다.

버튼을 누를 뿐 아니라 만약 화면 어느정도 부분에서 왼쪽 또는 오른쪽으로 슬라이드를 하면

그때도 drawer 창이 열리고 닫히는 것을 확인할 수 있다!

기본적으로 제공하는 네비게이션 창 외에도 이렇게 직접 만들어서 쓰는게 실무에서 더 유용할지도~