Last active
March 11, 2022 19:34
-
-
Save baruckis/f81b054a96e729bf214788e3572f698d to your computer and use it in GitHub Desktop.
WebView fragment for showing PDF in Kotlin for Android.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<!-- | |
~ Copyright 2019 Andrius Baruckis www.baruckis.com | |
~ | |
~ Licensed under the Apache License, Version 2.0 (the "License"); | |
~ you may not use this file except in compliance with the License. | |
~ You may obtain a copy of the License at | |
~ | |
~ http://www.apache.org/licenses/LICENSE-2.0 | |
~ | |
~ Unless required by applicable law or agreed to in writing, software | |
~ distributed under the License is distributed on an "AS IS" BASIS, | |
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
~ See the License for the specific language governing permissions and | |
~ limitations under the License. | |
--> | |
<androidx.constraintlayout.widget.ConstraintLayout 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" | |
tools:context=".WebViewPdfFragment"> | |
<WebView | |
android:id="@+id/webView" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
app:layout_constraintBottom_toBottomOf="parent" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toTopOf="parent" /> | |
<ProgressBar | |
android:id="@+id/progressBar" | |
style="?android:attr/progressBarStyle" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_margin="8dp" | |
app:layout_constraintBottom_toBottomOf="parent" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toTopOf="parent" /> | |
</androidx.constraintlayout.widget.ConstraintLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2019 Andrius Baruckis www.baruckis.com | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import android.annotation.SuppressLint | |
import android.os.Bundle | |
import android.text.TextUtils | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.webkit.WebChromeClient | |
import android.webkit.WebView | |
import android.webkit.WebViewClient | |
import android.widget.Toast | |
import androidx.fragment.app.Fragment | |
import kotlinx.android.synthetic.main.fragment_webview_pdf.* | |
class WebViewPdfFragment : Fragment() { | |
companion object { | |
const val KEY_URL = "key_url" | |
private const val PDF_VIEWER_URL = "https://docs.google.com/gview?embedded=true&url=" | |
private const val RELOAD_COUNT = "reload_count" | |
private const val RELOAD_ALLOW = 6 | |
fun newInstance(url: String): WebViewPdfFragment { | |
val fragment = WebViewPdfFragment() | |
val args = Bundle() | |
args.putString(KEY_URL, url) | |
fragment.arguments = args | |
return fragment | |
} | |
} | |
private var url: String? = null | |
private var reloadCount = 0 | |
override fun onCreateView(inflater: LayoutInflater, | |
container: ViewGroup?, | |
savedInstanceState: Bundle?): View? { | |
val view = inflater.inflate(R.layout.fragment_webview_pdf, container, false) | |
url = arguments?.getString(KEY_URL) | |
if (TextUtils.isEmpty(url)) { | |
throw IllegalArgumentException("Empty URL passed to WebViewFragment!") | |
} | |
return view | |
} | |
@SuppressLint("SetJavaScriptEnabled") | |
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
super.onViewCreated(view, savedInstanceState) | |
savedInstanceState?.let { | |
reloadCount = it.getInt(RELOAD_COUNT) | |
} | |
// Get the web view settings instance. | |
val settings = webView.settings | |
// Enable java script in web view. | |
settings.javaScriptEnabled = true | |
// Enable DOM storage API. | |
settings.domStorageEnabled = true | |
// Enable zooming in web view. | |
settings.setSupportZoom(true) | |
// Allow pinch to zoom. | |
settings.builtInZoomControls = true | |
// Disable the default zoom controls on the page. | |
settings.displayZoomControls = false | |
// Enable responsive layout. | |
settings.useWideViewPort = false | |
// Zoom out if the content width is greater than the width of the viewport. | |
settings.loadWithOverviewMode = false | |
// Set web view client. | |
webView.webChromeClient = object : DefaultWebChromeClient() { | |
override fun onProgressChanged(webView: WebView?, newProgress: Int) { | |
if (newProgress < 100) { | |
progressBar.visibility = View.VISIBLE | |
} | |
if (newProgress == 100) { | |
// There is a bug with Google Docs that sometimes you get blank screen | |
// instead of a PDF file. To avoid just reload when you get it. | |
if (webView?.contentHeight == 0 && reloadCount < RELOAD_ALLOW) { | |
Log.w("LOG_TAG", "PDF loading error. Reloading $reloadCount.") | |
Toast.makeText(activity, "Error. Reloading...", Toast.LENGTH_SHORT).show() | |
reloadCount++ | |
webView.reload() | |
} | |
progressBar.visibility = View.GONE | |
} | |
} | |
} | |
val urlString: String = PDF_VIEWER_URL + url | |
webView.loadUrl(urlString) | |
Log.d("LOG_TAG", "Loading URL: $url") | |
} | |
override fun onSaveInstanceState(outState: Bundle) { | |
outState.putInt(RELOAD_COUNT, reloadCount) | |
super.onSaveInstanceState(outState) | |
} | |
override fun onResume() { | |
super.onResume() | |
webView.onResume() | |
} | |
override fun onPause() { | |
super.onPause() | |
webView.onPause() | |
} | |
override fun onDestroyView() { | |
super.onDestroyView() | |
// Destroy the WebView completely. | |
if (webView != null) { | |
// The WebView must be removed from the view hierarchy before calling destroy to prevent a memory leak. | |
(webView.parent as ViewGroup).removeView(webView) | |
webView.removeAllViews() | |
webView.destroy() | |
} | |
} | |
fun onBackPressed(): Boolean { | |
if (webView.canGoBack()) { | |
// If web view have back history, then go to the web view back history. | |
webView.goBack() | |
return true | |
} | |
return false | |
} | |
internal open class DefaultWebViewClient : WebViewClient() { | |
// Decide how a new url will be loaded. If this method returns false, it means current | |
// webView will handle the url. If this method returns true, it means host application | |
// will handle the url. By default, redirects cause jump from WebView to default | |
// system browser. | |
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { | |
return true | |
} | |
} | |
internal open class DefaultWebChromeClient : WebChromeClient() { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment