Недавно мне было поручено создать приложение WebView на работе. Все работает отлично, кроме одной вещи. Когда он постукивает по нему, он исчезает. Элементы, стоящие за ним, кликабельны, поэтому пользователь рискует что -то нажать на что -то и отступать от экрана, в котором он был.@AndroidEntryPoint
class WebViewFragment : Fragment() {
private var _binding: FragmentWebViewBinding? = null
private val binding get() = _binding!!
private val viewModel: WebViewFragmentViewModel by viewModels()
private var pendingGpsHandler: String? = null
private var shouldEmulateOnRestore = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentWebViewBinding.inflate(inflater, container, false)
handleDeviceBackPress()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
shouldEmulateOnRestore = savedInstanceState != null
setupUI(savedInstanceState == null)
if (savedInstanceState != null) {
binding.webView.restoreState(savedInstanceState)
}
observeForAction()
requestNotificationsPermission()
}
override fun onPause() {
binding.webView.onPause()
viewModel.persistCookies()
super.onPause()
}
override fun onResume() {
super.onResume()
binding.webView.onResume()
binding.webView.resumeTimers()
if (viewModel.isCustomTabVisible) {
viewModel.isCustomTabVisible = false
viewModel.abortPayment()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.webView.saveState(outState)
}
@SuppressLint("JavascriptInterface")
private fun setupUI(shouldLoad: Boolean) {
val imageRes = if (viewModel.isEnglishPreSet()) R.drawable.ic_gregorys_english else R.drawable.ic_gregorys
binding.timeoutView.logoImageView.setImageResource(imageRes)
binding.timeoutView.timeoutTitleTextView.text = viewModel.getTimeoutString()
viewModel.enableCookies(binding.webView)
binding.webView.configureSettings()
binding.webView.webViewClient = createRobustWebViewClient()
binding.webView.addJavascriptInterface(
WebAppInterface { command, commandPayload ->
viewModel.processWebviewCommand(
command = command,
commandPayload = commandPayload
)
},
"AppWebInterface"
)
if (shouldLoad) binding.webView.loadUrl(viewModel.buildWebviewUrl())
}
private fun createRobustWebViewClient(): WebViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
viewModel.resetTimeOutCounter()
// if (restoreJustHappened) view?.emulateTap()
}
override fun onPageCommitVisible(view: WebView, url: String) {
super.onPageCommitVisible(view, url)
if (shouldEmulateOnRestore) {
// view.emulateTap()
shouldEmulateOnRestore = false
}
}
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
Log.d("ErrorDebugging", "error: $error")
if (!request.isForMainFrame) {
super.onReceivedError(view, request, error)
return
}
when (error.errorCode) {
ERROR_HOST_LOOKUP, ERROR_TIMEOUT -> viewModel.showTimeOutImmediately()
ERROR_CONNECT, ERROR_UNKNOWN -> viewModel.increaseTimeoutCounter()
else -> viewModel.resetTimeOutCounter()
}
super.onReceivedError(view, request, error)
}
}
// ...
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
< /code>
@SuppressLint("SetJavaScriptEnabled")
fun WebView.configureSettings(
lowEndDevice: Boolean = context.packageManager
.hasSystemFeature(PackageManager.FEATURE_RAM_LOW) ||
(context.getSystemService(ActivityManager::class.java)
?.isLowRamDevice == true)
) {
setWebContentsDebuggingEnabled(true)
// ───────────── WebSettings ───────────────────────────────────────────
settings.apply {
javaScriptEnabled = true // run site JavaScript
domStorageEnabled = true // enable localStorage / sessionStorage
databaseEnabled = true // enable Web SQL / IndexedDB
javaScriptCanOpenWindowsAutomatically = true // allow window.open()
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW// allow http inside https (payments)
allowContentAccess = true // content:// URIs
allowFileAccess = true // file:// URIs
setSupportMultipleWindows(false) // no new WebViews for pop-ups
mediaPlaybackRequiresUserGesture = false // autoplay videos
safeBrowsingEnabled = true // Google Safe-Browsing
useWideViewPort = true // respect
loadWithOverviewMode = true // zoom-out to fit width
builtInZoomControls = false // pinch-zoom widgets off
displayZoomControls = false // hide tiny +/- buttons
textZoom = 100 // ignore sys. font scale
cacheMode = WebSettings.LOAD_DEFAULT
setSupportZoom(false) // legacy zoom API off
// ---------- Legacy AppCache (API < 28) --------------------------
if (Build.VERSION.SDK_INT < 28) runCatching {
// use reflection so we can still compile with SDK 35
val enable = WebSettings::class.java.getMethod(
"setAppCacheEnabled",
Boolean::class.javaPrimitiveType
)
enable.invoke(this, true)
val path = WebSettings::class.java.getMethod(
"setAppCachePath", String::class.java)
path.invoke(this, context.cacheDir.absolutePath)
}.onFailure { Log.w("WebViewSettings", "AppCache not available", it) }
// offscreenPreRaster = !lowEndDevice // pre-raster on capable hw
// @Suppress("DEPRECATION")
// setRenderPriority(WebSettings.RenderPriority.HIGH) // smoother scroll (pre-KitKat)
}
// ───────────── Rendering layer ───────────────────────────────────────
// if (lowEndDevice)
// setLayerType(View.LAYER_TYPE_SOFTWARE, null) // CPU render (avoids GPU crashes)
// else
// setLayerType(View.LAYER_TYPE_HARDWARE, null) // GPU render for smoothness
// ───────────── Appearance ────────────────────────────────────────────
setBackgroundColor(Color.WHITE) // keep WebView background invisible
}
fun WebView.emulateTap() {
post {
val x = width - 1f
val y = 1f
val downTime = System.currentTimeMillis()
val eventTime = System.currentTimeMillis()
val motionEventDown = android.view.MotionEvent.obtain(
downTime,
eventTime,
android.view.MotionEvent.ACTION_DOWN,
x, y, 0
)
val motionEventUp = android.view.MotionEvent.obtain(
downTime,
eventTime + 50,
android.view.MotionEvent.ACTION_UP,
x, y, 0
)
dispatchTouchEvent(motionEventDown)
dispatchTouchEvent(motionEventUp)
motionEventDown.recycle()
motionEventUp.recycle()
requestFocus(View.FOCUS_DOWN)
dispatchWindowFocusChanged(true)
invalidate()
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... he-backgro
WebView показывает пустой экран, когда возвращается из приложения на фоне ⇐ Android
Форум для тех, кто программирует под Android
1748175153
Anonymous
Недавно мне было поручено создать приложение WebView на работе. Все работает отлично, кроме одной вещи. Когда он постукивает по нему, он исчезает. Элементы, стоящие за ним, кликабельны, поэтому пользователь рискует что -то нажать на что -то и отступать от экрана, в котором он был.@AndroidEntryPoint
class WebViewFragment : Fragment() {
private var _binding: FragmentWebViewBinding? = null
private val binding get() = _binding!!
private val viewModel: WebViewFragmentViewModel by viewModels()
private var pendingGpsHandler: String? = null
private var shouldEmulateOnRestore = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentWebViewBinding.inflate(inflater, container, false)
handleDeviceBackPress()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
shouldEmulateOnRestore = savedInstanceState != null
setupUI(savedInstanceState == null)
if (savedInstanceState != null) {
binding.webView.restoreState(savedInstanceState)
}
observeForAction()
requestNotificationsPermission()
}
override fun onPause() {
binding.webView.onPause()
viewModel.persistCookies()
super.onPause()
}
override fun onResume() {
super.onResume()
binding.webView.onResume()
binding.webView.resumeTimers()
if (viewModel.isCustomTabVisible) {
viewModel.isCustomTabVisible = false
viewModel.abortPayment()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.webView.saveState(outState)
}
@SuppressLint("JavascriptInterface")
private fun setupUI(shouldLoad: Boolean) {
val imageRes = if (viewModel.isEnglishPreSet()) R.drawable.ic_gregorys_english else R.drawable.ic_gregorys
binding.timeoutView.logoImageView.setImageResource(imageRes)
binding.timeoutView.timeoutTitleTextView.text = viewModel.getTimeoutString()
viewModel.enableCookies(binding.webView)
binding.webView.configureSettings()
binding.webView.webViewClient = createRobustWebViewClient()
binding.webView.addJavascriptInterface(
WebAppInterface { command, commandPayload ->
viewModel.processWebviewCommand(
command = command,
commandPayload = commandPayload
)
},
"AppWebInterface"
)
if (shouldLoad) binding.webView.loadUrl(viewModel.buildWebviewUrl())
}
private fun createRobustWebViewClient(): WebViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
viewModel.resetTimeOutCounter()
// if (restoreJustHappened) view?.emulateTap()
}
override fun onPageCommitVisible(view: WebView, url: String) {
super.onPageCommitVisible(view, url)
if (shouldEmulateOnRestore) {
// view.emulateTap()
shouldEmulateOnRestore = false
}
}
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
Log.d("ErrorDebugging", "error: $error")
if (!request.isForMainFrame) {
super.onReceivedError(view, request, error)
return
}
when (error.errorCode) {
ERROR_HOST_LOOKUP, ERROR_TIMEOUT -> viewModel.showTimeOutImmediately()
ERROR_CONNECT, ERROR_UNKNOWN -> viewModel.increaseTimeoutCounter()
else -> viewModel.resetTimeOutCounter()
}
super.onReceivedError(view, request, error)
}
}
// ...
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
< /code>
@SuppressLint("SetJavaScriptEnabled")
fun WebView.configureSettings(
lowEndDevice: Boolean = context.packageManager
.hasSystemFeature(PackageManager.FEATURE_RAM_LOW) ||
(context.getSystemService(ActivityManager::class.java)
?.isLowRamDevice == true)
) {
setWebContentsDebuggingEnabled(true)
// ───────────── WebSettings ───────────────────────────────────────────
settings.apply {
javaScriptEnabled = true // run site JavaScript
domStorageEnabled = true // enable localStorage / sessionStorage
databaseEnabled = true // enable Web SQL / IndexedDB
javaScriptCanOpenWindowsAutomatically = true // allow window.open()
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW// allow http inside https (payments)
allowContentAccess = true // content:// URIs
allowFileAccess = true // file:// URIs
setSupportMultipleWindows(false) // no new WebViews for pop-ups
mediaPlaybackRequiresUserGesture = false // autoplay videos
safeBrowsingEnabled = true // Google Safe-Browsing
useWideViewPort = true // respect
loadWithOverviewMode = true // zoom-out to fit width
builtInZoomControls = false // pinch-zoom widgets off
displayZoomControls = false // hide tiny +/- buttons
textZoom = 100 // ignore sys. font scale
cacheMode = WebSettings.LOAD_DEFAULT
setSupportZoom(false) // legacy zoom API off
// ---------- Legacy AppCache (API < 28) --------------------------
if (Build.VERSION.SDK_INT < 28) runCatching {
// use reflection so we can still compile with SDK 35
val enable = WebSettings::class.java.getMethod(
"setAppCacheEnabled",
Boolean::class.javaPrimitiveType
)
enable.invoke(this, true)
val path = WebSettings::class.java.getMethod(
"setAppCachePath", String::class.java)
path.invoke(this, context.cacheDir.absolutePath)
}.onFailure { Log.w("WebViewSettings", "AppCache not available", it) }
// offscreenPreRaster = !lowEndDevice // pre-raster on capable hw
// @Suppress("DEPRECATION")
// setRenderPriority(WebSettings.RenderPriority.HIGH) // smoother scroll (pre-KitKat)
}
// ───────────── Rendering layer ───────────────────────────────────────
// if (lowEndDevice)
// setLayerType(View.LAYER_TYPE_SOFTWARE, null) // CPU render (avoids GPU crashes)
// else
// setLayerType(View.LAYER_TYPE_HARDWARE, null) // GPU render for smoothness
// ───────────── Appearance ────────────────────────────────────────────
setBackgroundColor(Color.WHITE) // keep WebView background invisible
}
fun WebView.emulateTap() {
post {
val x = width - 1f
val y = 1f
val downTime = System.currentTimeMillis()
val eventTime = System.currentTimeMillis()
val motionEventDown = android.view.MotionEvent.obtain(
downTime,
eventTime,
android.view.MotionEvent.ACTION_DOWN,
x, y, 0
)
val motionEventUp = android.view.MotionEvent.obtain(
downTime,
eventTime + 50,
android.view.MotionEvent.ACTION_UP,
x, y, 0
)
dispatchTouchEvent(motionEventDown)
dispatchTouchEvent(motionEventUp)
motionEventDown.recycle()
motionEventUp.recycle()
requestFocus(View.FOCUS_DOWN)
dispatchWindowFocusChanged(true)
invalidate()
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79637650/webview-shows-a-blank-screen-when-coming-back-from-having-the-app-on-the-backgro[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия