Explanation
한동안 꾸준히 포스팅을 하나 했으나, 어느세 한달이 지나버렸네요..
오늘은 추석 연휴를 맞이하여, 마음을 다잡고 이것저것 공부도 좀 하고 포스팅도 좀 해보려고 합니다!!
그 첫번째로, 짧은 시간이지만 제가 약간 알아보고 사용해봤던 것들을 정리도 할 겸!!
투명한 액티비티(웹뷰) 만들기, 풀스크린 웹뷰 만들기, 웹뷰 링크 및 뒤로가기 구현하기를 묶어서 적어보려 합니다.
작성된 코드는 https://github.com/falsy/blog-post-example/tree/master/android-for-frontend/webview-others 에서 확인하실 수 있습니다!
1. 투명한 배경의 액티비티, 웹뷰 만들기
먼저 'TransparentActivity'라는 이름으로 액티비티를 만들어주었어요.
그리고 res/values/styles.xml 을 새로 만들어서 아래와 같이 추가해 주었습니다.

<!-- res/values/styles.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Transparent" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
windowIsTranslucent: 윈도우를 투명하게 설정
windowBackground: 윈도우 배경 색을 지정
windowContentOverlay: 일반적으로 타이틀 아래에 그림자를 그릴때 쓴다는데 뭔지 잘 모르겠네요..
(https://developer.android.com/reference/android/R.attr#windowContentOverlay)
windowNoTitle: 타이틀바 없애기
backgroundDimEnabled: 투명 앱티비티의 dimmed 영역을 사용할지??
다음으로 레이아웃 xml을 수정해 줄게요.
<!-- res/lauout/activity_transparent.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TransparentActivity">
<WebView
android:id="@+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
다음으로 TransparentActivity 액티비티를 수정해 줄게요.
// java/com.example.frontend/TransparentActivity
package com.example.frontend
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebView
class TransparentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transparent)
window.statusBarColor = Color.TRANSPARENT
val myWebView: WebView = findViewById(R.id.webView1)
myWebView.settings.javaScriptEnabled = true
myWebView.setBackgroundColor(0)
myWebView.loadUrl("http://10.0.2.2:8080")
}
}
코드는 간단하죠? 'window.statusBarColor = Color.TRANSPARENT' 로 상단바 색을 투명하게 하고 'myWebView.setBackgroundColor(0)' 로 웹뷰의 배경 색을 투명하게 설정해줬어요.
이제 마지막으로 매니페스트를 수정해줄게요.
<!-- manifests/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:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Frontend"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".TransparentActivity"
android:theme="@style/Theme.Transparent"
android:exported="false" />
<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>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
추가한 내용은 대충, TransparentActivity 라는 액티비티에 'android:theme="@style/Theme.Transparent"'라는 속성을 추가했어요. 아까 만들었던 styles.xml에 투명한 테마를 액티비티에 적용하였습니다.
끝!

캡처가 헷갈랄 수 있는데.. hello world가 투명한 새로운 액티비티의 웹뷰로 위에 떠 있는거에요.
2. 풀스크린 웹뷰
그냥 단순하게 액티비티의 상단바를 투명하게 하는건 앞 서 작성했던 것처럼, 'window.statusBarColor = Color.TRANSPARENT' 로 설정할 수 있는데요.
여기서 적으려고 하는 내용은, 풀스크린으로 적용하는 방법을 적어보려합니다.
풀스크린 웹뷰를 사용하면 상단바의 영역까지도 웹뷰의 영역에 포함하기 때문에 다이얼로그를 띄울때 dimmed 처리도 웹뷰내에서 직접 할 수 있는 장점이 있답니다!
// java/com.example.frontend/TransparentActivity
package com.example.frontend
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebView
class TransparentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transparent)
window.statusBarColor = Color.TRANSPARENT
window.setDecorFitsSystemWindows(false)
val myWebView: WebView = findViewById(R.id.webView1)
myWebView.settings.javaScriptEnabled = true
myWebView.setBackgroundColor(0)
myWebView.loadUrl("http://10.0.2.2:8080")
}
}
풀스크린으로 웹뷰를 사용하는 건 간단한데요. 'window.setDecorFitsSystemWindows(false)' 이렇게 속성을 한줄 넣어주면 된답니다!
추가로!
웹뷰가 상단바(+ 네비게이션바)의 영역을 포함한 영역을 갖게되지만, 그래도 일반적으로 상단바 영역은 잘 사용하지 않는데요. 그래서 웹뷰에서 상단바의 영역을 비워놓는 처리가 필요하답니다.
안드로이드에서는 상단바나 네비게이션바 높이값을 알 수 있는데요. 이 값과 ratio 값을 이용해서 웹뷰에서는 상단바(+ 네비게이션바)의 영역을 비워둘 수 있답니다.
// java/com.example.frontend/TransparentActivity
package com.example.frontend
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebView
class TransparentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transparent)
window.statusBarColor = Color.TRANSPARENT
window.setDecorFitsSystemWindows(false)
val statusBarId = resources.getIdentifier("status_bar_height", "dimen", "android")
val navBarId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
val statusBarHeight = resources.getDimensionPixelSize(statusBarId)
val navigationHeight = resources.getDimensionPixelSize(navBarId)
val ratio = resources.displayMetrics.scaledDensity
val statusHeight = statusBarHeight/ratio
val navHeight = navigationHeight/ratio
val myWebView: WebView = findViewById(R.id.webView1)
myWebView.settings.javaScriptEnabled = true
myWebView.loadUrl("http://10.0.2.2:8080/?statusHeight=${statusHeight}&navHeight=${navHeight}")
}
}
짜잔 대략적으로 이렇게 웹뷰의 쿼리스트링으로 상단바와 네비게이션바의 높이값을 전달해 줄 수 있습니다!
ratio 값은 브라우저에서도 'window.devicePixelRatio' 값으로 구할 수 있으니, 전달하는 값은 선택적으로 할 수 있을 거 같아요.
3. 웹뷰 링크 연결하기
안드로이드 웹뷰에서의 기본 링크는 외부 브라우저로 연결되서 출력이되는데요.
// java/com.example.frontend/TransparentActivity
package com.example.frontend
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebView
class MyWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
view?.loadUrl(request?.url.toString())
return super.shouldOverrideUrlLoading(view, request)
}
}
class TransparentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transparent)
val myWebView: WebView = findViewById(R.id.webView1)
myWebView.settings.javaScriptEnabled = true
myWebView.webViewClient = MyWebViewClient()
myWebView.loadUrl("http://10.0.2.2:8080")
}
}
짜잔, 이렇게 웹뷰 클라이언트의 shouldOverrideUrlLoading를 오버라이드해주면 된답니다!
그러면 이제 링크를 누르면 웹뷰 내에서 페이지가 이동됩니다.
4. 웹뷰 뒤로가기
기본적으로 디바이스의 백키(혹은 네비게이션의 백키)를 누르면 기본적으로는 가장 위에 있는 스택을 종료하는데요.
// java/com.example.frontend/TransparentActivity
package com.example.frontend
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.WebView
class MyWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
view?.loadUrl(request?.url.toString())
return super.shouldOverrideUrlLoading(view, request)
}
}
class TransparentActivity : AppCompatActivity() {
private lateinit var myWebView: WebView;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transparent)
myWebView = findViewById(R.id.webView1)
myWebView.settings.javaScriptEnabled = true
myWebView.webViewClient = MyWebViewClient()
myWebView.loadUrl("http://10.0.2.2:8080")
}
override fun onBackPressed() {
if (myWebView.canGoBack()) {
myWebView.goBack()
} else {
super.onBackPressed()
}
}
}
위와 같이 onBackPressed를 오버라이드해서, 디바이스의 백키가 스택을 종료하는 게 아닌 웹뷰의 히스토리 백으로 동작하고 더 이상 히스토리가 없을때 스택을 종료가 되도록 구성할 수 있답니다!



