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;로 변경합니다. 이렇게 하면 터치 이벤트가 현재 뷰에서만 처리되고 다른 뷰로 전달되지 않습니다.
마지막으로 결과물을 보겠습니다.
'Android Studio' 카테고리의 다른 글
[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - Fragment (9) (0) | 2023.11.05 |
---|---|
[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - RecyclerView (8) (1) | 2023.11.03 |
[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - LIstView, SharedPreferences (6) (1) | 2023.11.01 |
[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - ImageView, AndroidManifest, values (5) (0) | 2023.11.01 |
[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - Intent (4) (0) | 2023.10.31 |