본문 바로가기
Android Studio

[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - WebView, Navigation Menu (7)

by jisayDeveloper 2023. 11. 2.
728x90
반응형
SMALL

WebView

WebView는 앱에서 웹 페이지를 출력할 때 사용합니다. 여러 다른 어플에서도 이와 같은 방식을 많이 봤을텐데 직접 구현해보겠습니다.

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <WebView
        android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
</LinearLayout>

흰 바탕화면만 사용하려고 match_parent로 통일합니다.

 

MainActivity

package com.example.webview;

import android.view.KeyEvent;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    WebView webView;
    String url = "https://jisayportfolio.netlify.app";

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

        webView = (WebView) findViewById(R.id.webView);

        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl(url);
        webView.setWebChromeClient(new WebChromeClient());
        webView.setWebViewClient(new WebViewClientClass());

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()){
            webView.goBack();
        }
        return super.onKeyDown(keyCode, event);
    }

    private class WebViewClientClass extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        
            view.loadUrl(url);
            return true;
        }
    }
}

 

WebView를 선언하고 연결해서 보여줄 웹 주소 url를 초기화합니다. (저는 저의 포트폴리오 사이트를 연결할겁니다.)

 

webView.getSettings().setJavaScriptEnabled(true);

 

위 코드는 WebView에서 JavaScript를 활성화 합니다. 이러면 JavaScript를 사용하는 웹 페이지를 로드하고 상호 작용 할 수 있습니다.

 

//웹페이지가 로딩될 때 생기는 콜백 함수들로 구성, 웹 페이지 로딩의 시작과 끝을 알 수 있다.
webView.setWebChromeClient(new WebChromeClient());

//웹페이지에서 일어나는 콜백 함수들로 구성, 대표적으로 새 창을 띄우거나 파일을 첨부하는 경우다.
webView.setWebViewClient(new WebViewClientClass());

이 코드들은 webView 속 버튼을 앱에서 제어하기 위해 필요한 구현체입니다.

 

private class WebViewClientClass extends WebViewClient는 내부 클래스로 WebViewClient를 상속하여 새로운 웹 페이지 로딩 및 페이지 이동을 처리합니다.

 

shouldOverridingUrlLoading()는 webView에서 url이 로딩될떄 호출되어 앱에게 제어할 기회를 줍니다. 앱이 url로딩을 제어할 경우 true 반대는 false

 

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()){
        webView.goBack();
    }
    return super.onKeyDown(keyCode, event);
}

이 코드에선 만약 사용자가 뒤로가기 버튼을 눌렀을 때, webView가 더 이전 페이지로 갈 수 있다면 이전 페이지로 가고 아니라면 디폴트 동작을 수행하게 합니다.

 

그리고 인터넷 권한을 줘야지만 Webview가 정상적으로 실행됩니다. 권한은 AndroidManifest.xml에서 줄 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools">
    
    //인터넷 권한부여
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/Theme.WebView"
            tools:targetApi="31">
        <activity
                android:name=".MainActivity"
                android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

 

이제 WebView가 잘 나오는지 확인해보겠습니다.

 


Navigation Menu

정말 유용하게 사용할 수 있는 Navigation Menu 만드는 법을 보겠습니다.

일단 menu창을 따로 만들어 주기 위해 새로운 xml 파일을 만듭니다.

res/layout 우클릭 → New → Layout Resorce File 

이름은 activity_drawer로 했습니다.

 

activity_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="240dp" //메뉴창을 240dp만큼만 사용합니다.
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#71EDF1"
        android:id="@+id/drawer_view" 
        android:orientation="vertical">

    <Button
        android:id="@+id/btn_close"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="close"/>

    <TextView

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="jisay menu"/>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="#4DEBAC"
            android:orientation="vertical">

        <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="test menu"/>



    </LinearLayout>

</LinearLayout>

 

<LinearLayout>안에 <LinearLayout>을 정의하고 그 안에 TextView를 사용할 수도 있습니다.

 

 

activity_main.xml

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

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

        <Button
                android:id="@+id/btn_open"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="open"/>

    </LinearLayout>
    <include layout="@layout/activity_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>

 

activity_main 에선 <LinearLayout>대신 <DrawerLayout>을 사용합니다.

그리고 drawer 오픈 버튼, <Include>를 통해서 drawer를 연결합니다.

 

이제 자바를 코딩할텐데 설정이 많아서 하나 하나 잘라서 설명하겠습니다.

 

MainActivity

private DrawerLayout drawerLayout; //메인 액티비티
private View drawerView; //드로어 액티비티
Button btn_open = (Button) findViewById(R.id.btn_open);
        btn_open.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                drawerLayout.openDrawer(drawerView);
            }
        });

Button btn_close = (Button) findViewById(R.id.btn_close);
		btn_close.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                drawerLayout.closeDrawers();
            }
		});

open버튼과 close버튼에 이벤트를 겁니다.

 

여기까지만 구현해도 네비게이션 메뉴는 잘 나타나고 열고 닫는데 문제가 없을 겁니다.

그러나 더 나아가서 관련 설정을 조금 더 알아 보겠습니다.

 

drawerLayout.setDrawerListener(listener);
        drawerView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
    }
    
    
    
DrawerLayout.DrawerListener listener = new DrawerLayout.DrawerListener() {

        //슬라이드 할때
        @Override
        public void onDrawerSlide(@NonNull @NotNull View drawerView, float slideOffset) {

        }

        //열었을 때
        @Override
        public void onDrawerOpened(@NonNull @NotNull View drawerView) {

        }

        // 닫았을 때
        @Override
        public void onDrawerClosed(@NonNull @NotNull View drawerView) {

        }

        //상태 바뀔 때
        @Override
        public void onDrawerStateChanged(int newState) {

        }
    };

drawerLayout.setDrawerListener(listener);: 이 코드는 drawerLayout (네비게이션 드로어를 관리하는 레이아웃)에 대한 드로어 리스너(listener)를 설정합니다. 드로어 리스너는 드로어의 열기 또는 닫기 상태 변경을 감지하고 적절한 작업을 수행할 수 있도록 합니다.

 

drawerView.setOnTouchListener(new View.OnTouchListener() { ... });: 이 코드는 drawerView (네비게이션 드로어의 내용물을 나타내는 뷰)에 대한 터치 이벤트 리스너를 설정합니다. 터치 이벤트 리스너는 사용자의 터치 동작을 감지하고 해당 동작에 대한 처리를 정의할 수 있도록 합니다.

  •   return true;는 이 터치 이벤트 리스너가 기본적으로 return false;를 반환하여 터치 이벤트를 소비하지 않고 상위 뷰로 전달합니다. 따라서 이 뷰의 터치 이벤트가 다른 뷰에도 전달됩니다. 그러나 터치 이벤트를 소비하려면 return true;로 변경합니다. 이렇게 하면 터치 이벤트가 현재 뷰에서만 처리되고 다른 뷰로 전달되지 않습니다.

마지막으로 결과물을 보겠습니다.

 

 

728x90
반응형
LIST