Android WebView全屏视频退出创建额外的空白区域
Posted
技术标签:
【中文标题】Android WebView全屏视频退出创建额外的空白区域【英文标题】:Android WebView full screen video exit create extra blank white space 【发布时间】:2020-12-13 19:24:53 【问题描述】:我有一个 android web 应用程序,我想在其中隐藏系统栏和导航栏以全屏模式播放视频。一切正常,没有任何问题。
我的 MainActivity 的原始视图如下图所示。
但是当我退出全屏模式时会出现问题。每当我退出全屏视频时,都会创建一些空白区域。
我已经尝试过使用 YouTube、Vimeo 和 Dailymotion。但是所有这些网站的问题仍然存在。下面我给出了他们的演示,他们从全屏模式退出后的样子。
YouTube:
Vimeo:
每日运动:
这是我的 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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_
android:layout_
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<ProgressBar
android:id="@+id/mainProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_
android:layout_
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:max="100"
android:visibility="gone" />
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/mainSrl"
android:layout_
android:layout_
android:layout_above="@id/mainControllerContainer"
android:layout_below="@id/mainProgressBar">
<com.jobayr.webapp.ObservableWebView
android:id="@+id/mainWebView"
android:layout_
android:layout_ />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/mainControllerContainer"
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@color/colorPrimary"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="4">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mainControllerBackBtn"
android:layout_
android:layout_
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="12dp"
app:srcCompat="@drawable/icon_back" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mainControllerRefreshBtn"
android:layout_
android:layout_
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="12dp"
app:srcCompat="@drawable/icon_refresh" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mainControllerHomeBtn"
android:layout_
android:layout_
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="12dp"
app:srcCompat="@drawable/icon_home" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mainControllerForwardBtn"
android:layout_
android:layout_
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="12dp"
app:srcCompat="@drawable/icon_forward" />
</LinearLayout>
</RelativeLayout>
MainActivity.kt
class MainActivity : AppCompatActivity(), AdvancedWebView.Listener
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
override fun onCreateOptionsMenu(menu: Menu?): Boolean
menuInflater.inflate(R.menu.mian_menu, menu)
return super.onCreateOptionsMenu(menu)
override fun onOptionsItemSelected(item: MenuItem): Boolean
if (item.itemId == R.id.miClearCookies)
AlertDialog.Builder(this)
.setTitle("Clear Data")
.setMessage("Are you sure you want to delete browser data?")
.setPositiveButton("Delete") _, _ ->
WebStorage.getInstance().deleteAllData()
CookieManager.getInstance().removeAllCookies(null)
CookieManager.getInstance().flush()
mainWebView.clearCache(true)
mainWebView.clearFormData()
mainWebView.clearHistory()
mainWebView.clearSslPreferences()
.setNegativeButton("Cancel", null)
.show()
else if (item.itemId == R.id.miExit)
AlertDialog.Builder(this)
.setTitle("Confirmation")
.setMessage("Are you sure you want to exit?")
.setPositiveButton("YES") _, _ ->
finishAffinity()
.setNegativeButton("CANCEL", null)
.show()
return super.onOptionsItemSelected(item)
override fun onResume()
super.onResume()
mainWebView.onResume()
override fun onPause()
super.onPause()
mainWebView.onPause()
override fun onDestroy()
super.onDestroy()
mainWebView.onDestroy()
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
super.onActivityResult(requestCode, resultCode, data)
mainWebView.onActivityResult(requestCode, resultCode, data)
private fun init()
goOn()
initCallback()
private fun goOn()
val permissionListener = object : PermissionListener
override fun onPermissionGranted()
initWebView()
override fun onPermissionDenied(deniedPermissions: MutableList<String>?)
AlertDialog.Builder(this@MainActivity)
.setTitle("Permission Required")
.setMessage("Kindly grant all the permission to use this app")
.setPositiveButton("Retry") _, _ ->
goOn()
.setNegativeButton("Cancel") _, _ ->
finishAffinity()
.show()
TedPermission.with(this)
.setPermissionListener(permissionListener)
.setDeniedMessage("You need to grant all the permission to use this app")
.setPermissions(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
.check()
@SuppressLint("SetjavascriptEnabled")
private fun initWebView()
mainWebView.loadUrl(getString(R.string.url), true)
mainWebView.settings.javaScriptEnabled = true
mainWebView.setListener(this, this)
mainWebView.settings.javaScriptCanOpenWindowsAutomatically = true
mainWebView.webViewClient = WebViewClient()
mainWebView.settings.setSupportZoom(false)
mainWebView.settings.displayZoomControls = false
mainWebView.setCookiesEnabled(true)
mainWebView.setThirdPartyCookiesEnabled(true)
mainWebView.setMixedContentAllowed(true)
mainWebView.webChromeClient = CustomChromeClient(this, mainProgressBar)
private fun initCallback()
mainControllerBackBtn.setOnClickListener
if (mainWebView.canGoBack())
mainWebView.goBack()
else Toast.makeText(this, "Going Back Is Not Available", Toast.LENGTH_SHORT)
.show()
mainControllerRefreshBtn.setOnClickListener
mainWebView.reload()
mainControllerHomeBtn.setOnClickListener
mainWebView.loadUrl(getString(R.string.url), true)
mainControllerForwardBtn.setOnClickListener
if (mainWebView.canGoForward())
mainWebView.goForward()
else Toast.makeText(this, "Going Forward Is Not Available", Toast.LENGTH_SHORT)
.show()
mainSrl.setOnRefreshListener
mainWebView.reload()
mainWebView.setOnScrollChangedCallback _, t, _, oldt ->
if (t > oldt)
if (t - oldt >= 60)
supportActionBar?.hide()
mainControllerContainer.visibility = View.GONE
else if (t < oldt)
if (oldt - t >= 60)
supportActionBar?.show()
mainControllerContainer.visibility = View.VISIBLE
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean
if (event!!.action == KeyEvent.ACTION_DOWN)
when (keyCode)
KeyEvent.KEYCODE_BACK ->
if (mainWebView.canGoBack())
mainWebView.goBack()
else
AlertDialog.Builder(this)
.setTitle("Confirmation")
.setMessage("Are you sure you want to exit?")
.setPositiveButton("YES") _, _ ->
finishAffinity()
.setNegativeButton("CANCEL", null)
.show()
return true
return super.onKeyDown(keyCode, event)
override fun onPageFinished(url: String?)
if (mainSrl.isRefreshing)
mainSrl.isRefreshing = false
override fun onPageError(errorCode: Int, description: String?, failingUrl: String?)
if (mainSrl.isRefreshing)
mainSrl.isRefreshing = false
description?.let
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
override fun onDownloadRequested(
url: String?,
suggestedFilename: String?,
mimeType: String?,
contentLength: Long,
contentDisposition: String?,
userAgent: String?
)
try
if (AdvancedWebView.handleDownload(this, url, suggestedFilename))
Toast.makeText(this, "Download Started", Toast.LENGTH_LONG).show()
else
AlertDialog.Builder(this)
.setTitle("Download Error")
.setMessage("Couldn't download $suggestedFilename. Make sure your download manager is working properly.")
.setPositiveButton("OK", null)
.show()
catch (e: Exception)
AlertDialog.Builder(this)
.setTitle("Download Error")
.setMessage(e.message.toString())
.setPositiveButton("OK", null)
.show()
override fun onExternalPageRequest(url: String?)
mainWebView.loadUrl(url, true)
override fun onPageStarted(url: String?, favicon: Bitmap?)
CustomChromeClient.java
public class CustomChromeClient extends WebChromeClient
private Activity activity;
private ProgressBar progressBar;
private View mCustomView;
private WebChromeClient.CustomViewCallback mCustomViewCallback;
private int mOriginalOrientation;
private int mOriginalSystemUiVisibility;
CustomChromeClient(Activity activity, ProgressBar progressBar)
this.activity = activity;
this.progressBar = progressBar;
public Bitmap getDefaultVideoPoster()
if (mCustomView == null)
return null;
return BitmapFactory.decodeResource(activity.getResources(), 2130837573);
@Override
public void onProgressChanged(WebView view, int newProgress)
super.onProgressChanged(view, newProgress);
if (newProgress < 100)
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(newProgress);
else
progressBar.setVisibility(View.GONE);
progressBar.setProgress(0);
public void onHideCustomView()
this.mCustomViewCallback.onCustomViewHidden();
this.mCustomViewCallback = null;
((FrameLayout) activity.getWindow().getDecorView()).removeView(this.mCustomView);
this.mCustomView = null;
activity.getWindow().getDecorView().setSystemUiVisibility(this.mOriginalSystemUiVisibility);
activity.setRequestedOrientation(this.mOriginalOrientation);
activity.getWindow().getDecorView().invalidate();
public void onShowCustomView(View paramView, WebChromeClient.CustomViewCallback paramCustomViewCallback)
if (this.mCustomView != null)
onHideCustomView();
return;
this.mCustomView = paramView;
this.mOriginalSystemUiVisibility = activity.getWindow().getDecorView().getSystemUiVisibility();
this.mOriginalOrientation = activity.getRequestedOrientation();
this.mCustomViewCallback = paramCustomViewCallback;
((FrameLayout) activity.getWindow().getDecorView()).addView(this.mCustomView, new FrameLayout.LayoutParams(-1, -1));
activity.getWindow().getDecorView().setSystemUiVisibility(3846 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
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"
package="com.demo.webapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:ignore="AllowBackup,UnusedAttribute">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout|keyboard|layoutDirection|uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
OvservableWebView.java 这不是感兴趣的主题(如果我没记错的话。这主要是为了检测我的 webview 的滚动行为。但是我正在发布它也是。)
public class ObservableWebView extends AdvancedWebView
private OnScrollChangedCallback mOnScrollChangedCallback;
public ObservableWebView(final Context context)
super(context);
public ObservableWebView(final Context context, final AttributeSet attrs)
super(context, attrs);
public ObservableWebView(final Context context, final AttributeSet attrs, final int defStyle)
super(context, attrs, defStyle);
@Override
protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt)
super.onScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedCallback != null) mOnScrollChangedCallback.onScroll(l, t, oldl, oldt);
public OnScrollChangedCallback getOnScrollChangedCallback()
return mOnScrollChangedCallback;
public void setOnScrollChangedCallback(final OnScrollChangedCallback onScrollChangedCallback)
mOnScrollChangedCallback = onScrollChangedCallback;
public static interface OnScrollChangedCallback
public void onScroll(int l, int t, int oldl, int oldt);
请帮我解决这个问题。任何解决方案,想法将不胜感激。提前致谢。
【问题讨论】:
嘿,你找到解决办法了吗?我面临同样的问题,但尝试从 Android 系统更改导航按钮的布局。仅当我的导航使用按钮并且导航使用手势时才会发生这种情况 不,兄弟,我还没有找到任何解决方案。是的,这些只有在导航按钮可见时才会发生 【参考方案1】:我找到了解决办法!
您必须使用此存储库中的类:https://github.com/cprcrack/VideoEnabledWebView。
这是由 Stack Overflow 用户创建的存储库,用于帮助和改进在 Android WebView 中全屏播放 html 视频。
您可以在 another user answer
中看到它这是唯一对我有用的解决方案。
【讨论】:
【参考方案2】:我找到了解决办法。
从RelativeLayout
中删除android:fitsSystemWindows="true"
,这将删除视图顶部的空白区域。
【讨论】:
以上是关于Android WebView全屏视频退出创建额外的空白区域的主要内容,如果未能解决你的问题,请参考以下文章
如何解决在android开发中WebView在线播放视频黑屏啊?
Android Webview 应用程序不会让视频播放器全屏显示
关闭全屏视图后的Android WebView Video,webview自动滚动