Hide WebView until JavaScript is done

16,071

Solution 1

Tested on API 17 emulator and it works.

You can inject javascript from Java to the web.

And do vice-versa, once the url is loaded call from javascript to a function on our Java code, and execute the setVisibility(). For that purpose you are going to add a JS interface.

Here the code:

private final static String HOST = "stackoverflow.com";
private WebView wb;

@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_home);
    wb = (WebView) findViewById(R.id.home_webview);
    //Make the webview invisible
    wb.setVisibility(View.INVISIBLE);
    WebSettings webSettings = wb.getSettings();
    webSettings.setJavaScriptEnabled(true);
    wb.setWebViewClient(new WebViewClient(){
        public void onPageFinished(WebView view, String url){
            //Inject javascript code to the url given
            //Not display the element
            wb.loadUrl("javascript:(function(){"+"document.getElementById('Id').style.display ='none';"+"})()");
            //Call to a function defined on my myJavaScriptInterface 
            wb.loadUrl("javascript: window.CallToAnAndroidFunction.setVisible()");
        }           
    });

    //Add a JavaScriptInterface, so I can make calls from the web to Java methods
    wb.addJavascriptInterface(new myJavaScriptInterface(), "CallToAnAndroidFunction");
    wb.loadUrl("http://"+HOST);
}

 public class myJavaScriptInterface {
     @JavascriptInterface
     public void setVisible(){
         runOnUiThread(new Runnable() {

            @Override
            public void run() {
                wb.setVisibility(View.VISIBLE);                 
            }
        });
     }

 }

This functionality is going to be executed for every page. Once on the 3rd party server you have to manage what to do with every request, webClient.shouldOverrideUrlLoading() can help you.

Updated answer:

I could reproduce it as you commented, for the last version we should do:

Beginning in Android 4.2, you will now have to explicitly annotate public methods with @JavascriptInterface in order to make them accessible from hosted JavaScript. Note that this also only takes effect only if you have set your app's minSdkVersion or targetSdkVersion to 17 or higher.

I added it and imported android.webkit.JavascriptInterface

Reference: JavascriptInterface methods in WebViews must now be annotated

Solution 2

I had the same problem of @GromDroid.

Maybe not the best solution but it works:

public class myJavaScriptInterface {
        @JavascriptInterface
        public void setVisible(){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            wb.setVisibility(View.VISIBLE);
                        }
                    }, 500);
                }
            });
        }
    }

I've added a delay of half second before make the webview visible.

Share:
16,071
GromDroid
Author by

GromDroid

Updated on June 20, 2022

Comments

  • GromDroid
    GromDroid about 2 years

    I have a webview

    WebView wv;
    wv = (WebView)findViewById(R.id.webView1);
    wv.loadUrl("http://example.com/");
    

    Simply said.

    at:

    onPageFinished
    

    I have:

    wv.loadUrl("javascript:(function() { " + "document.getElementsByClassName('centered leaderboard_container')[0].style.display = 'none'; " + "document.getElementsByClassName('n')[0].style.display = 'none'; " + "document.getElementsByClassName('paginator')[0].style.display = 'none'; " + "document.getElementsByTagName('ul')[0].style.display = 'none'; " + "document.getElementsByTagName('tr')[0].style.display = 'none'; " + "})()");
    

    I've set webview visibility to INVISIBLE

    How can I set visibility to VISIBLE after the JavaScript is done?

    Now you get to see the whole page for a second and than the JavaScript is done..

    Anyone?

    ps. The website is not mine, its a 3rd party website

  • GromDroid
    GromDroid about 11 years
    Hmmm, this doesn't work on my Galaxy Nexus 4.2.2 Do you know what could be wrong? @AlexBcn
  • GromDroid
    GromDroid about 11 years
    I still see the 'whole' page for a second and than the JavaScript hide the elements.. @AlexBcn
  • AlexBcn
    AlexBcn about 11 years
    Put javascript:(function(){"+"document.getElementById('Id').styl‌​e.display ='none';"+"window.CallToAnAndroidFunction.setVisible();})() instead of splitting the two script on two loadUrls. If the webview was setted to invisible, setVisible will be the last command to be executted.
  • GromDroid
    GromDroid about 11 years
    So weird, it still doesn't work for me.. Can you maybe send me an APK or project ZIP so I could test your version? @AlexBcn
  • GromDroid
    GromDroid about 11 years
    I downloaded it, I will try now
  • GromDroid
    GromDroid about 11 years
    Sorry, I decided to do a completely native rebuild instead of using WebView, I'll accept your answer because you tried to help me :D