Hide elements from WebView with JavaScript ( Android )

60 views Asked by At

I'm trying to remove a banner and the footer from a website I'm loading into a WebView.

So far my code is working without any issues

But the the challenge now is when I navigate the website for example opening a link, the banner and footer is displayed for a second until the page is fully loaded. I know I can only manipulate the data after its loaded since I can't access the server of the website I'm loading but I think there has to be a way to get around this issue?

I would be very happy to get some ideas.

Here is my code so far:

class HomeFragment : Fragment() {

private var _binding: FragmentHomeBinding? = null

// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    val homeViewModel =
        ViewModelProvider(this).get(HomeViewModel::class.java)

    _binding = FragmentHomeBinding.inflate(inflater, container, false)
    val root: View = binding.root


    return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    val myWebView: WebView = view.findViewById(R.id.webview1)

    fun removeElement(myWebView: WebView ) {

        myWebView.loadUrl("javascript:(function() { document.getElementById('banner').style.display='none';})()")
        myWebView.loadUrl("javascript:(function() { document.getElementsByTagName(\"footer\")[0].style.display='none';})()")
     
    }


    myWebView.webViewClient = object : WebViewClient() {


        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
            removeElement(view!!)
        }

    }

    myWebView.loadUrl("The URL I'm loading")
    myWebView.settings.javaScriptEnabled = true
    myWebView.setOnKeyListener { v, keyCode, event ->
        if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) {
            myWebView.goBack() // Navigate back to previous web page if there is one

        }
        true
    }
    lateinit var swipeRefreshLayout: SwipeRefreshLayout
    swipeRefreshLayout = view.findViewById(R.id.swipe_container)
    swipeRefreshLayout.setOnRefreshListener {
        myWebView.reload()
        swipeRefreshLayout.isRefreshing = false
    }
    

}
override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

}

1

There are 1 answers

5
Pratik Prakash Bindage On
  • The issue you're facing is due to the asynchronous nature of web page loading. When you navigate to a new page, the JavaScript code to remove the banner and footer is executed only after the new page has finished loading. This results in the banner and footer being displayed for a short period before being hidden.

  • Use a WebViewClient that waits for the page to fully load before removing the banner and footer. You can achieve this by extending the WebViewClient class and overriding the onPageFinished method.

    class HomeFragment : Fragment() {
    
      private var _binding: FragmentHomeBinding? = null
    
      // This property is only valid between onCreateView and
      // onDestroyView.
      private val binding get() = _binding!!
    
      override fun onCreateView(
          inflater: LayoutInflater,
          container: ViewGroup?,
          savedInstanceState: Bundle?
      ): View {
          val homeViewModel =
              ViewModelProvider(this).get(HomeViewModel::class.java)
    
          _binding = FragmentHomeBinding.inflate(inflater, container, false)
          val root: View = binding.root
    
          return root
      }
    
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          super.onViewCreated(view, savedInstanceState)
    
          val myWebView: WebView = view.findViewById(R.id.webview1)
    
          fun removeElement(myWebView: WebView) {
              myWebView.evaluateJavascript("javascript:(function() { document.getElementById('banner').style.display='none';})()", null)
              myWebView.evaluateJavascript("javascript:(function() { document.getElementsByTagName(\"footer\")[0].style.display='none';})()", null)
          }
    
          myWebView.webViewClient = object : WebViewClient() {
    
              private var isPageLoaded = false
    
              override fun onPageFinished(view: WebView?, url: String?) {
                  super.onPageFinished(view, url)
                  if (!isPageLoaded) {
                      removeElement(view!!)
                      isPageLoaded = true
                  }
              }
    
              override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                  isPageLoaded = false
                  return super.shouldOverrideUrlLoading(view, request)
              }
          }
    
          myWebView.loadUrl("The URL I'm loading")
          myWebView.settings.javaScriptEnabled = true
          myWebView.setOnKeyListener { v, keyCode, event ->
              if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) {
                  myWebView.goBack() // Navigate back to previous web page if there is one
                  isPageLoaded = false
              }
              true
          }
    
          lateinit var swipeRefreshLayout: SwipeRefreshLayout
          swipeRefreshLayout = view.findViewById(R.id.swipe_container)
          swipeRefreshLayout.setOnRefreshListener {
              myWebView.reload()
              swipeRefreshLayout.isRefreshing = false
          }
      }
    
      override fun onDestroyView() {
          super.onDestroyView()
          _binding = null
      }
    }
    
  • In this code, the shouldOverrideUrlLoading method is overridden to intercept link clicks and load them within the same WebView. The removeElement function is called before the new page is loaded, so the banner and footer are removed immediately. This should prevent the banner and footer from being displayed on reload or when navigating.

    class HomeFragment : Fragment() {
    
    private var _binding: FragmentHomeBinding? = null
    
      // This property is only valid between onCreateView and
      // onDestroyView.
      private val binding get() = _binding!!
    
      override fun onCreateView(
          inflater: LayoutInflater,
          container: ViewGroup?,
          savedInstanceState: Bundle?
      ): View {
          val homeViewModel =
              ViewModelProvider(this).get(HomeViewModel::class.java)
    
          _binding = FragmentHomeBinding.inflate(inflater, container, false)
          val root: View = binding.root
    
          return root
      }
    
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          super.onViewCreated(view, savedInstanceState)
    
          val myWebView: WebView = view.findViewById(R.id.webview1)
    
          fun removeElement(myWebView: WebView) {
              myWebView.evaluateJavascript("javascript:(function() { document.getElementById('banner').style.display='none';})()", null)
              myWebView.evaluateJavascript("javascript:(function() { document.getElementsByTagName(\"footer\")[0].style.display='none';})()", null)
          }
    
          myWebView.webViewClient = object : WebViewClient() {
    
              private var isPageLoaded = false
    
              override fun onPageFinished(view: WebView?, url: String?) {
                  super.onPageFinished(view, url)
                  if (!isPageLoaded) {
                      removeElement(view!!)
                      isPageLoaded = true
                  }
              }
    
              override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                  isPageLoaded = false
                  view?.loadUrl(request?.url.toString())
                  removeElement(view)
                  return true
              }
          }
    
          myWebView.loadUrl("The URL I'm loading")
          myWebView.settings.javaScriptEnabled = true
          myWebView.setOnKeyListener { v, keyCode, event ->
              if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) {
                  myWebView.goBack() // Navigate back to previous web page if there is one
                  isPageLoaded = false
              }
              true
          }
    
          lateinit var swipeRefreshLayout: SwipeRefreshLayout
          swipeRefreshLayout = view.findViewById(R.id.swipe_container)
          swipeRefreshLayout.setOnRefreshListener {
              myWebView.reload()
              swipeRefreshLayout.isRefreshing = false
          }
      }
    
      override fun onDestroyView() {
          super.onDestroyView()
          _binding = null
      }
    }