fix:修复百顺游戏时飘屏无法展示问题(由Activity改为View-Fragment实现)

This commit is contained in:
max
2024-05-08 11:36:46 +08:00
parent 9ae80b839b
commit ea92c08ca1
11 changed files with 374 additions and 225 deletions

View File

@@ -41,7 +41,10 @@ import androidx.viewpager2.widget.ViewPager2;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chwl.app.notify.RoomNotifyManager;
import com.chwl.app.ui.webview.baishun.BaiShunGameWebFragment;
import com.chwl.app.ui.webview.baishun.IBaiShunGameListener;
import com.chwl.core.monsterhunting.bean.MonsterDataBean;
import com.chwl.core.room.game.bean.BaiShunGameConfig;
import com.chwl.core.support.room.RoomWidget;
import com.netease.nim.uikit.StatusBarUtil;
import com.netease.nimlib.sdk.NIMSDK;
@@ -219,6 +222,8 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
private RoomNotifyManager roomNotify;
private BaiShunGameWebFragment baiShunGameFragment;
public static void start(Context context, long roomUid) {
startForFromType(context, roomUid, FROM_TYPE_NORMAL, null, null);
}
@@ -917,7 +922,9 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
@Override
public void onBackPressed() {
if (closeBaiShunGame()) {
return;
}
if (AvRoomDataManager.get().isGamePlaying(AvRoomDataManager.get().getMicPosition(AuthModel.get().getCurrentUid()))) {
getDialogManager().showOkCancelDialog(ResUtil.getString(R.string.avroom_activity_avroomactivity_09), false,
this::minRoomCode);
@@ -1441,4 +1448,30 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
}
}
}
public void showBaiShunGame(String url, BaiShunGameConfig config) {
closeBaiShunGame();
baiShunGameFragment = BaiShunGameWebFragment.Companion.newInstance(url, config);
baiShunGameFragment.setListener(new IBaiShunGameListener() {
@Override
public void onGameClose() {
closeBaiShunGame();
}
});
findViewById(R.id.layout_baishun_game).setVisibility(VISIBLE);
getSupportFragmentManager().beginTransaction().add(R.id.layout_baishun_game, baiShunGameFragment).commitAllowingStateLoss();
}
private boolean closeBaiShunGame() {
boolean isClose = false;
if (baiShunGameFragment != null) {
if (baiShunGameFragment.isAdded()) {
getSupportFragmentManager().beginTransaction().remove(baiShunGameFragment).commitAllowingStateLoss();
isClose = true;
}
}
findViewById(R.id.layout_baishun_game).setVisibility(View.GONE);
baiShunGameFragment = null;
return isClose;
}
}

View File

@@ -29,6 +29,9 @@ class RoomGameplayDialog :
private var binding: RoomGameplayDialogBinding? = null
private var compositeDisposable: CompositeDisposable? = null
private val adapter = RoomGameplayAdapter()
var listener: RoomGameplayDialog.GameplayDialogListener? = null
override fun getTheme(): Int {
return R.style.ErbanBottomSheetDialogDimFalse
}
@@ -181,7 +184,8 @@ class RoomGameplayDialog :
)
if (config != null && url != null) {
config.reloadDynamicParams()
BaiShunGameWebActivity.start(requireContext(), url, config)
listener?.onShowBaiShunGame(url, config)
// BaiShunGameWebActivity.start(requireContext(), url, config)
} else {
SingleToastUtil.showToast(R.string.manager_trtc_trtcengineadapter_042)
}
@@ -189,4 +193,8 @@ class RoomGameplayDialog :
e.printStackTrace()
}
}
interface GameplayDialogListener {
fun onShowBaiShunGame(url: String, config: BaiShunGameConfig)
}
}

View File

@@ -36,6 +36,7 @@ import com.chwl.app.R
import com.chwl.app.avroom.BottomViewListenerWrapper
import com.chwl.app.avroom.SoftKeyBoardListener
import com.chwl.app.avroom.SoftKeyBoardListener.OnSoftKeyBoardChangeListener
import com.chwl.app.avroom.activity.AVRoomActivity
import com.chwl.app.avroom.activity.RoomInviteActivity
import com.chwl.app.avroom.activity.RoomTitleEditActivity
import com.chwl.app.avroom.adapter.OnMicroItemClickListener
@@ -98,6 +99,7 @@ import com.chwl.core.room.bean.RoomInfo
import com.chwl.core.room.event.RoomAtEvent
import com.chwl.core.room.event.RoomClearScreenEvent
import com.chwl.core.room.game.GameStatus
import com.chwl.core.room.game.bean.BaiShunGameConfig
import com.chwl.core.room.giftvalue.helper.GiftValueMrg
import com.chwl.core.room.queue.bean.MicMemberInfo
import com.chwl.core.share.bean.SessionType
@@ -1421,7 +1423,13 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
}
override fun onRoomGameplayClick() {
RoomGameplayDialog().show(childFragmentManager, "ROOM_GAME_PLAY")
val dialog = RoomGameplayDialog()
dialog.listener = object : RoomGameplayDialog.GameplayDialogListener {
override fun onShowBaiShunGame(url: String, config: BaiShunGameConfig) {
(activity as? AVRoomActivity)?.showBaiShunGame(url, config)
}
}
dialog.show(childFragmentManager, "ROOM_GAME_PLAY")
}
}

View File

@@ -11,7 +11,7 @@ import org.json.JSONObject
@Keep
class BaiShunGameJSBridge(val activity: BaiShunGameWebActivity) : ILog {
class BaiShunGameJSBridge(val view: IBaiShunGameView) : ILog {
@JavascriptInterface
public fun getConfig(params: String) {
@@ -19,7 +19,7 @@ class BaiShunGameJSBridge(val activity: BaiShunGameWebActivity) : ILog {
try {
val obj = JSONObject(params)
val jsFunName = obj.optString("jsCallback")
val config = activity.getGameConfig()
val config = view.getGameConfig()
val str = (jsFunName + "(" + Gson().toJson(config) + ")")
callJs(str)
} catch (ex: Exception) {
@@ -30,16 +30,16 @@ class BaiShunGameJSBridge(val activity: BaiShunGameWebActivity) : ILog {
@JavascriptInterface
public fun destroy(params: String) {
logD("游戏调⽤destroy")
activity.runOnUiThread {
activity.finish()
view.getActivity2()?.runOnUiThread {
view.getListener()?.onGameClose()
}
}
@JavascriptInterface
public fun gameRecharge(params: String) {
logD("游戏调⽤gameRecharge")
activity.runOnUiThread {
DialogUiHelper.showNeedCharge(activity, activity.dialogManager)
view.getActivity2()?.runOnUiThread {
DialogUiHelper.showNeedCharge(view.getActivity2(), view.getDialogManager2())
}
}
@@ -47,12 +47,12 @@ class BaiShunGameJSBridge(val activity: BaiShunGameWebActivity) : ILog {
public fun gameLoaded(params: String) {
logD("游戏调⽤gameLoaded")
//游戏加载完毕
activity.runOnUiThread {
activity.dialogManager.dismissDialog()
view.getActivity2()?.runOnUiThread {
view.getDialogManager2().dismissDialog()
}
}
private fun callJs(str: String) {
activity.callJs(str)
view.callJs(str)
}
}

View File

@@ -1,45 +1,17 @@
package com.chwl.app.ui.webview.baishun
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.net.http.SslError
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import android.webkit.SslErrorHandler
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener
import com.chwl.app.databinding.RoomGameActivityBinding
import com.chwl.core.auth.AuthModel
import com.chwl.core.pay.event.GetWalletInfoEvent
import com.chwl.core.pay.event.UpdateWalletInfoEvent
import com.chwl.core.room.game.bean.BaiShunGameConfig
import com.chwl.library.utils.ResUtil
import com.google.gson.Gson
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@Deprecated("改用房间内View-Fragment实现了暂且保留一阵时间")
class BaiShunGameWebActivity : BaseViewBindingActivity<RoomGameActivityBinding>() {
private var gameConfig: BaiShunGameConfig? = null
private var gameUrl = ""
private var isLoadError = false
companion object {
fun start(context: Context, url: String, config: BaiShunGameConfig) {
val intent = Intent(context, BaiShunGameWebActivity::class.java)
@@ -59,189 +31,19 @@ class BaiShunGameWebActivity : BaseViewBindingActivity<RoomGameActivityBinding>(
WindowManager.LayoutParams.MATCH_PARENT
)
val url = intent.getStringExtra("url")
gameConfig = intent.getSerializableExtra("config") as? BaiShunGameConfig
val gameConfig = intent.getSerializableExtra("config") as? BaiShunGameConfig
if (url.isNullOrEmpty() || gameConfig == null) {
toast(R.string.utils_net_beanobserver_05)
finish()
return
}
gameUrl = url
initView()
binding.webView.isInvisible = true
binding.webView.loadUrl(url)
}
private fun initView() {
initWebView()
}
@SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
private fun initWebView() {
//防⽌⽤浏览器打开⽹⻚
binding.webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
isLoadError = false
if (url == gameUrl) {
dialogManager.showProgressDialog(this@BaiShunGameWebActivity)
}
val fragment = BaiShunGameWebFragment.newInstance(url, gameConfig)
fragment.setListener(object : IBaiShunGameListener {
override fun onGameClose() {
finish()
}
override fun onReceivedError(
view: WebView?,
errorCode: Int,
description: String?,
failingUrl: String?
) {
super.onReceivedError(view, errorCode, description, failingUrl)
isLoadError = true
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
onReceivedError(failingUrl, errorCode, description)
}
}
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
super.onReceivedError(view, request, error)
isLoadError = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
onReceivedError(request?.url?.toString(), error?.errorCode, error?.description)
}
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
if (!isLoadError) {
binding.webView.isVisible = true
}
}
override fun onReceivedSslError(
view: WebView,
handler: SslErrorHandler,
error: SslError?
) {
// super.onReceivedSslError(view, handler, error);
val builder = AlertDialog.Builder(view.context)
builder.setMessage(ResUtil.getString(R.string.ui_webview_commonwebviewactivity_07))
builder.setPositiveButton(
ResUtil.getString(R.string.ui_webview_commonwebviewactivity_08)
) { dialog, which ->
handler.proceed() // 接受https所有网站的证书
}
builder.setNegativeButton(
ResUtil.getString(R.string.ui_webview_commonwebviewactivity_09)
) { dialog, which -> handler.cancel() }
val dialog = builder.create()
dialog.show()
}
}
//设置webview背景透明,默认为⽩⾊
binding.webView.setBackgroundColor(0)
//设置view背景透明默认为⽩⾊ 可选(单独activity添加webView组件时需要添加)
binding.root.setBackgroundColor(0)
val settings = binding.webView.settings
//设置⽀持Javascript
settings.javaScriptEnabled = true
//设置默认⽂本编码
settings.defaultTextEncodingName = "UTF-8"
//设置可访问本地⽂件
settings.allowFileAccess = true
//设置允许通过file url加载的Javascript读取全部资源(包括⽂件,http,https)
settings.allowUniversalAccessFromFileURLs = true
//设置优先加载缓存
settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
//设置启⽤HTML5 DOM storage
settings.domStorageEnabled = true
//设置开启数据库缓存
settings.databaseEnabled = true
settings.databasePath = (applicationContext.filesDir.absolutePath)
//设置⽀持缩放
settings.setSupportZoom(true)
//设置⾃适应
settings.useWideViewPort = true
//设置⾃动播放媒体
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
settings.mediaPlaybackRequiresUserGesture = false
}
//设置5.0以上允许加载http和https混合的⻚⾯
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
//游戏调⽤的类,必须定义为 NativeBridge
binding.webView.addJavascriptInterface(BaiShunGameJSBridge(this), "NativeBridge")
}
fun callJs(str: String) {
binding.webView.post {
binding.webView.loadUrl("javascript:$str")
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onWalletInfoUpdate(event: UpdateWalletInfoEvent?) {
updateGameWallet()
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onGetWalletInfoEvent(event: GetWalletInfoEvent?) {
updateGameWallet()
}
private fun updateGameWallet() {
try {
//数据只是参考值需要根据⾃⼰APP进⾏赋值
val map = HashMap<String, Any>()
map["userId"] = AuthModel.get().currentUid
val str = "walletUpdate" + "(" + Gson().toJson(map) + ")"
this.callJs(str)
} catch (e: Exception) {
e.printStackTrace()
}
}
fun getGameConfig() = gameConfig
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
EventBus.getDefault().register(this)
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
private fun onReceivedError(url: String?, code: Int?, message: CharSequence?) {
if (url == gameUrl) {
binding.webView.isInvisible = true
dialogManager.dismissDialog()
showLoadErrorDialog(message?.toString() ?: "($code)")
}
}
private fun showLoadErrorDialog(message: String) {
dialogManager.showOkCancelDialog(
getString(R.string.load_failed),
message,
getString(R.string.retry),
getString(R.string.exit_text),
false, false, true, object : OkCancelDialogListener {
override fun onOk() {
binding.webView.reload()
}
override fun onCancel() {
super.onCancel()
finish()
}
}, null, false
)
})
supportFragmentManager.beginTransaction().add(R.id.layout_body, fragment)
.commitAllowingStateLoss()
}
}

View File

@@ -0,0 +1,261 @@
package com.chwl.app.ui.webview.baishun
import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.Bitmap
import android.net.http.SslError
import android.os.Build
import android.os.Bundle
import android.webkit.SslErrorHandler
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingFragment
import com.chwl.app.common.widget.dialog.DialogManager
import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener
import com.chwl.app.databinding.RoomGameActivityBinding
import com.chwl.app.databinding.RoomGameFragmentBinding
import com.chwl.core.auth.AuthModel
import com.chwl.core.pay.event.GetWalletInfoEvent
import com.chwl.core.pay.event.UpdateWalletInfoEvent
import com.chwl.core.room.game.bean.BaiShunGameConfig
import com.chwl.library.utils.ResUtil
import com.google.gson.Gson
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class BaiShunGameWebFragment : BaseViewBindingFragment<RoomGameFragmentBinding>(),
IBaiShunGameView {
private var gameConfig: BaiShunGameConfig? = null
private var gameUrl = ""
private var isLoadError = false
private var listener: IBaiShunGameListener? = null
companion object {
fun newInstance(
url: String,
config: BaiShunGameConfig
): BaiShunGameWebFragment {
val bundle = Bundle()
bundle.putString("url", url)
bundle.putSerializable("config", config)
return BaiShunGameWebFragment().apply {
arguments = bundle
}
}
}
override fun init() {
val url = arguments?.getString("url")
gameConfig = arguments?.getSerializable("config") as? BaiShunGameConfig
if (url.isNullOrEmpty() || gameConfig == null) {
toast(R.string.utils_net_beanobserver_05)
return
}
gameUrl = url
initView()
binding.webView.isInvisible = true
binding.webView.loadUrl(url)
}
private fun initView() {
initWebView()
}
@SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
private fun initWebView() {
//防⽌⽤浏览器打开⽹⻚
binding.webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
isLoadError = false
if (url == gameUrl) {
dialogManager.showProgressDialog(requireContext())
}
}
override fun onReceivedError(
view: WebView?,
errorCode: Int,
description: String?,
failingUrl: String?
) {
super.onReceivedError(view, errorCode, description, failingUrl)
isLoadError = true
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
onReceivedError(failingUrl, errorCode, description)
}
}
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
super.onReceivedError(view, request, error)
isLoadError = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
onReceivedError(request?.url?.toString(), error?.errorCode, error?.description)
}
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
if (!isLoadError) {
binding.webView.isVisible = true
}
}
override fun onReceivedSslError(
view: WebView,
handler: SslErrorHandler,
error: SslError?
) {
// super.onReceivedSslError(view, handler, error);
val builder = AlertDialog.Builder(view.context)
builder.setMessage(ResUtil.getString(R.string.ui_webview_commonwebviewactivity_07))
builder.setPositiveButton(
ResUtil.getString(R.string.ui_webview_commonwebviewactivity_08)
) { dialog, which ->
handler.proceed() // 接受https所有网站的证书
}
builder.setNegativeButton(
ResUtil.getString(R.string.ui_webview_commonwebviewactivity_09)
) { dialog, which -> handler.cancel() }
val dialog = builder.create()
dialog.show()
}
}
//设置webview背景透明,默认为⽩⾊
binding.webView.setBackgroundColor(0)
//设置view背景透明默认为⽩⾊ 可选(单独activity添加webView组件时需要添加)
binding.root.setBackgroundColor(0)
val settings = binding.webView.settings
//设置⽀持Javascript
settings.javaScriptEnabled = true
//设置默认⽂本编码
settings.defaultTextEncodingName = "UTF-8"
//设置可访问本地⽂件
settings.allowFileAccess = true
//设置允许通过file url加载的Javascript读取全部资源(包括⽂件,http,https)
settings.allowUniversalAccessFromFileURLs = true
//设置优先加载缓存
settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
//设置启⽤HTML5 DOM storage
settings.domStorageEnabled = true
//设置开启数据库缓存
settings.databaseEnabled = true
settings.databasePath = (requireContext().applicationContext.filesDir.absolutePath)
//设置⽀持缩放
settings.setSupportZoom(true)
//设置⾃适应
settings.useWideViewPort = true
//设置⾃动播放媒体
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
settings.mediaPlaybackRequiresUserGesture = false
}
//设置5.0以上允许加载http和https混合的⻚⾯
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
//游戏调⽤的类,必须定义为 NativeBridge
binding.webView.addJavascriptInterface(BaiShunGameJSBridge(this), "NativeBridge")
}
override fun callJs(str: String) {
binding.webView.post {
binding.webView.loadUrl("javascript:$str")
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onWalletInfoUpdate(event: UpdateWalletInfoEvent?) {
updateGameWallet()
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onGetWalletInfoEvent(event: GetWalletInfoEvent?) {
updateGameWallet()
}
private fun updateGameWallet() {
try {
//数据只是参考值需要根据⾃⼰APP进⾏赋值
val map = HashMap<String, Any>()
map["userId"] = AuthModel.get().currentUid
val str = "walletUpdate" + "(" + Gson().toJson(map) + ")"
this.callJs(str)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun getGameConfig() = gameConfig
override fun getListener(): IBaiShunGameListener? {
return listener
}
fun setListener(listener: IBaiShunGameListener) {
this.listener = listener
}
override fun getActivity2(): Activity? {
return activity
}
override fun getDialogManager2(): DialogManager {
return super.getDialogManager()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
EventBus.getDefault().register(this)
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
private fun onReceivedError(url: String?, code: Int?, message: CharSequence?) {
if (url == gameUrl) {
binding.webView.isInvisible = true
dialogManager.dismissDialog()
showLoadErrorDialog(message?.toString() ?: "($code)")
}
}
private fun showLoadErrorDialog(message: String) {
dialogManager.showOkCancelDialog(
getString(R.string.load_failed),
message,
getString(R.string.retry),
getString(R.string.exit_text),
false, false, true, object : OkCancelDialogListener {
override fun onOk() {
binding.webView.reload()
}
override fun onCancel() {
super.onCancel()
listener?.onGameClose()
}
}, null, false
)
}
}

View File

@@ -0,0 +1,5 @@
package com.chwl.app.ui.webview.baishun
interface IBaiShunGameListener {
fun onGameClose()
}

View File

@@ -0,0 +1,19 @@
package com.chwl.app.ui.webview.baishun
import android.app.Activity
import android.content.Context
import com.chwl.app.base.BaseActivity
import com.chwl.app.common.widget.dialog.DialogManager
import com.chwl.core.room.game.bean.BaiShunGameConfig
interface IBaiShunGameView {
fun getActivity2(): Activity?
fun callJs(str: String)
fun getDialogManager2(): DialogManager
fun getGameConfig(): BaiShunGameConfig?
fun getListener(): IBaiShunGameListener?
}

View File

@@ -36,4 +36,10 @@
android:layout_marginBottom="150dp"
android:layout="@layout/layout_vs_task_tips" />
<FrameLayout
android:visibility="gone"
android:id="@+id/layout_baishun_game"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#66000000" />
</FrameLayout>

View File

@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_body"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>