如何解决Android WebView全屏视频出口创建额外的空白空间
我有一个android webapp,我想在其中以隐藏系统栏和导航栏的全屏模式播放视频。一切正常,没有任何问题。
我的MainActivity的原始视图如下图所示。
但是当我从全屏模式退出时,会出现问题。每当我退出全屏视频时,都会创建很少的空白区域。
我尝试过使用YouTube,Vimeo和Dailymotion。但是所有这些站点仍然存在问题。下面我给出了他们的演示,退出全屏模式后的样子。
YouTube:
Vimeo:
DailyMotion:
这是我的 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_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<ProgressBar
android:id="@+id/mainProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/mainControllerContainer"
android:layout_below="@id/mainProgressBar">
<com.jobayr.webapp.ObservableWebView
android:id="@+id/mainWebView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/mainControllerContainer"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
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_width="0dp"
android:layout_height="match_parent"
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_width="0dp"
android:layout_height="match_parent"
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_width="0dp"
android:layout_height="match_parent"
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_width="0dp"
android:layout_height="match_parent"
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,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,oldl,oldt);
if (mOnScrollChangedCallback != null) mOnScrollChangedCallback.onScroll(l,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);
}
}
请帮助我解决这个问题。任何解决方案,想法将不胜感激。预先感谢。
解决方法
我找到了解决方案!
您必须使用此存储库中的类:https://github.com/cprcrack/VideoEnabledWebView。
这是一个由 Stack Overflow 用户创建的存储库,用于帮助和改进在 Android WebView 中全屏播放 HTML 视频。
您可以在 another user answer
中看到它这是唯一对我有用的解决方案。
,我找到了解决方案。
从您的 android:fitsSystemWindows="true"
中删除 RelativeLayout
,这将删除视图顶部的空白区域。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。