如何在Android应用WebView中动态修改网页CSS样式?
Great question! Dynamically adjusting CSS in a WebView based on SharedPreferences is a common use case for theme switching or user-customized styles. Let’s break down a few practical approaches you can implement right away:
Approach 1: Replace CSS Link During HTML Loading
If you want to set the correct stylesheet before the page loads, modify the HTML content to point to the right CSS file based on your SharedPreferences value, then load the updated HTML into the WebView.
First, fetch your theme preference:
SharedPreferences prefs = getSharedPreferences("AppPreferences", MODE_PRIVATE); String activeTheme = prefs.getString("selected_theme", "light"); // Default to light theme
Next, load your local HTML file (from assets) and replace the stylesheet link. Assume your HTML has a placeholder link tag like <link id="theme-style" rel="stylesheet" href="">:
// Helper method to read HTML from assets private String loadHtmlFromAssets(String filename) { try { InputStream inputStream = getAssets().open(filename); int size = inputStream.available(); byte[] buffer = new byte[size]; inputStream.read(buffer); inputStream.close(); return new String(buffer, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); return "<html><body>Error loading page</body></html>"; } } // Update HTML and load into WebView String originalHtml = loadHtmlFromAssets("index.html"); String updatedHtml = originalHtml.replace( "<link id=\"theme-style\" rel=\"stylesheet\" href=\"\">", "<link id=\"theme-style\" rel=\"stylesheet\" href=\"" + activeTheme + ".css\">" ); webView.loadDataWithBaseURL("file:///android_asset/", updatedHtml, "text/html", "UTF-8", null);
Approach 2: Dynamically Swap CSS File with JavaScript
If you need to switch styles after the page has already loaded (e.g., user changes theme in settings without restarting the app), use JavaScript to update the existing stylesheet link.
First, enable JavaScript in your WebView:
WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true);
Then, when your SharedPreference value changes, run a JavaScript snippet to update the link's href attribute:
String newTheme = prefs.getString("selected_theme", "light"); String jsScript = "document.getElementById('theme-style').setAttribute('href', '" + newTheme + ".css');"; // Execute the script webView.evaluateJavascript(jsScript, new ValueCallback<String>() { @Override public void onReceiveValue(String value) { // Optional: Handle callback if needed } });
Note: Make sure your HTML's stylesheet tag has the id="theme-style" attribute so the JavaScript can target it.
Approach 3: Inject Custom CSS Directly
If you don’t need to swap entire stylesheets and just want to tweak specific styles, inject a custom CSS block directly into the page using JavaScript:
// Example: Apply dark mode styles String customCss = "body { background-color: #1a1a1a !important; color: #ffffff !important; }" + ".container { border-color: #333333 !important; }"; String injectCssScript = "var styleElement = document.createElement('style'); " + "styleElement.innerHTML = '" + customCss.replace("'", "\\'") + "'; " + "document.head.appendChild(styleElement);"; webView.evaluateJavascript(injectCssScript, null);
The !important flag ensures your injected styles override existing ones where necessary.
Bonus: Listen for SharedPreference Changes
To automatically update the WebView when the user changes their theme preference, register a listener:
prefs.registerOnSharedPreferenceChangeListener((sharedPreferences, key) -> { if ("selected_theme".equals(key)) { String updatedTheme = sharedPreferences.getString(key, "light"); // Use either Approach 2 or reload the page with Approach 1 updateWebViewTheme(updatedTheme); } }); // Helper method to handle theme updates private void updateWebViewTheme(String theme) { String jsScript = "document.getElementById('theme-style').setAttribute('href', '" + theme + ".css');"; webView.evaluateJavascript(jsScript, null); }
All these methods work seamlessly with SharedPreferences and let you tailor the WebView's appearance based on user settings.
内容的提问来源于stack exchange,提问作者kfir88

