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中制作嵌入视频全屏

关闭全屏视图后的Android WebView Video,webview自动滚动

webview 中的视频应在 android 中的 onShowCustomView() 方法上全屏显示

带有嵌入式 youtube 视频的 Android WebView,全屏按钮冻结视频