I've run into a problem when using <input type="password"> fields in a WebView on Honeycomb devices. Any time the view is scrolled, the screen flickers black and can even stay all black (except that it will draw the focused password field) once scrolling ends. I've seen this on all three Honeycomb tablets I've checked.
I can load the same HTML in the Browser app and I do not see this issue. I've tried changing many of the settings on the WebSettings/WebChromeClient/WebViewClient of the WebView and had no luck there. I've loaded the code below on a Froyo tablet and this issue did not occur, so it seems like a Honeycomb specific issue.
Has anyone seen this before? I'm at a loss on how to fix or workaround this issue currently.
Here's a short code sample that reproduces the issue. Simply focus the password field and scroll up and down. There's a password type input field and a text type input field, just to show that the issue does not occur with the text type field. The <div> tag is there simply to make it easier to scroll around and see the issue, although the issue still occurs without the <div> tag.
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class PasswordFieldTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webview = new WebView(this);
String html = "<html><body><div style=\"with: 120%; height: 200%; border: 20px dashed black;\">" +
"Password: <input type=\"password\" name=\"passfield\"/><br/>" +
"Text: <input type=\"text\" name=\"textfield\"/>" +
"</div></body></html>";
webview.loadData(html, "text/html", "utf-8");
setContentView(webview);
}
}
After trying everything suggested here, this finally worked for me on all the phones:
android:hardwareAccelerated="true"
AND:
if (android.os.Build.VERSION.SDK_INT < 16) {
webView.setBackgroundColor(0x00000000);
} else {
webView.setBackgroundColor(Color.argb(1, 0, 0, 0));
}
Please let me know if you find a phone this doesn't work on.
Works with these phones:
note2 (4.1.2)
htc one x (4.0.4)
galaxy s3 (4.3)
nexus4 (4.3)
This is a known issue in honeycomb devices.
However this one worked for me -
Compatibility.getCompatibility().setWebSettingsCache(webSettings);
Make sure to implement a Compatibility layer, since following method doesn't work in SDK_INT < 11.
webViewInstance.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
List of solutions suggested are here.
This sounds like a android:cacheColorHint issue. Try setting it to transparent in the WebView's attribute set.
For me android:layer="software" in the xml layout file works fine.
Related
I am using the HTML5 video element for playing video in the Android WebView. And this works great for me but the only problem with using this is that the video element automatically a gray play button adds.
I've tried searching for an API and could not find anything that helps my case. I also tried using CSS with the following style:
video.mobile_controls::-webkit-media-controls-fullscreen-button
{
display: inline !important; // Also used "display:none"
}
Further i tried poking in the shadow dom but i couldn't find anything related to this.
So the question is how do i remove this gray button.
Here is an image for reference:
The issue is the video poster. But there's a better way of fixing this by extending from the WebChromeClient and overriding the getDefaultVideoPoster();
Here is the solution:
import android.graphics.Bitmap;
import android.webkit.WebChromeClient;
public class WebChromeClientCustomPoster extends WebChromeClient {
#Override
public Bitmap getDefaultVideoPoster() {
return Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
}
}
And then using this client instead by doing:
WebChromeClientCustomPoster chromeClient = new WebChromeClientCustomPoster();
mWebView.setWebChromeClient(chromeClient);
After some dirty hacks we found that misusing the poster attribute fixed this issue. We resolved this issue by doing the following:
videoElement.setAttribute("poster", "nope");
The video element will use the value "nope" as its poster. And because nope is not a valid URL the video element will not replace the poster and will not show a poster.
Our team had tried to solve the same issue for a while too. What ultimately worked for us is setting this setting on the WebView webView.settings.mediaPlaybackRequiresUserGesture = false. Hope it helps others running into this too.
I observed that the Android Webview gets stuck when I try to tap into and focus on a TEXTAREA that is read-only and empty. The keyboard comes up and of course doesn't input anything into the TEXTAREA, but after that the WebView is stuck.
I can only force dismiss the keyboard using the "BACK" key but no other actions are performed. Can't do anything except restart the whole application.
<textarea rows="3" id="abcd" readonly="readonly" name="abcd"></textarea>
I keep getting this Verbose Message in the LOGCAT console against webview.
singleCursorHandlerTouchEVent ~getEditableSupport FASLE
This happens only on the Samsung S3 device running Android 4.1.1 and works perfectly on Samsung Nexus S (Android 4.1.2) and 4.1.2 Android emulator.
Other solutions proposed in these links did not work
Phonegap TouchEvent
Phonegap button does not fire due to "singleCursorHandlerTouchEvent -getEditableSupport FASLE"
This issue can be reproduced easily with this Standalone Webview example
public class TestWebViewTextStylesActivity extends Activity {
WebView mWebView = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String data = "<html><body>" +
"<textarea rows='3' id='abcd' readonly='readonly' name='abcd'></textarea>" +
"</body></html>";
mWebView = new WebView(this);
setContentView(mWebView);
// Set some HTML
mWebView.loadDataWithBaseURL("file:///android_asset/", data, "text/html", "UTF-8", null);
}
}
I found the solution after spending half a day looking at various alternatives.
The solution was very simple which was to introduce a space between the TEXTAREA html tags.
<textarea rows="3" id="abcd" readonly="readonly" name="abcd"> </textarea>
_____________________________________________________________||___________
________________________________________________INSERTED___SPACE ___HERE__
And I've also observed that setting the .innerText attribute to BLANK string via JS also causes the TEXTAREA to cause Webview Freeze.
That space is also required without which the browser assumes all the HTML followed by the TEXTAREA also belongs inside the TEXTAREA. So correct way is to give a single space and then complete the TEXTAREA (</TEXTAREA>)
For Writable TEXTAREA HTML elements you can't have this empty space or this gets prefixed with the value that's inputted by the user. So I had to write a JS method that will empty out the value that I had to inject before setting it to the WebView.
function clearOffTextArea(textAreaId) {
var x = document.getElementById(textAreaId);
var isReadOnly = false;
if (x.hasAttribute('readOnly')) {
isReadOnly = x.readOnly;
}
if (isReadOnly == false) {
if (customMethodToTrimString(x.innerText) == '') {
x.innerText = '';
}
}
}
I struggled so much to have a fixed background inside the webview.
First I tried this using CSS, But I found out background-attachment:fixed doesn't work in android, at least till 4 (don't know about newer versions).
The other option was to have a scrollable DIV which android doesn't support either.
I didn't try iscroll for this problem, but earlier used it somewhere else and wasn't satisfied. I don't know if it's possible with an iframe.
The other option was to set the background using android. I read much about this and tried many thing, one for example was using a container layout with a background and setting webview background to transparent.
It worked in 2.2 with a delay, in 4 it didn't work at all.
I'm so tired wasting a lot of time to achieve this small thing.
Do you have any other idea to implement this?
I finally found a solution:
This is how you do it:
First make your project base on 11, but in AndroidManifest set minSdkVersion to 8
wv.setBackgroundColor(0x00000000);
if (Build.VERSION.SDK_INT >= 11) wv.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
this.wv.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
wv.setBackgroundColor(0x00000000);
if (Build.VERSION.SDK_INT >= 11) wv.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
}
});
For safety put this in your style:
BODY, HTML {background: transparent}
worked for me on 2.2 and 4
I've seen/heard all about disabling text selection with the variations of user-select, but none of those are working for the problem I'm having. On Android (and I presume on iPhone), if you tap-and-hold on text, it highlights it and brings up little flags to drag and select text. I need to disable those (see image):
I've tried -webkit-touch-callout to no avail, and even tried things like $('body').on('select',function(e){e.preventDefault();return;}); to no avail. And the cheap tricks like ::selection:rgba(0,0,0,0); won't work either, as hiding these won't help - selection still happens and it disrupts the UI. Plus I'm guessing those flags would still be there.
Any thoughts would be great. Thanks!
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
-webkit-tap-highlight-color:rgba(0,0,0,0);
This will disable it for every browser going.
Reference:
jsFiddle Demo with Plugin
The above jsFiddle Demo I made uses a Plugin to allow you to prevent any block of text from being selected in Android or iOS devices (along with desktop browsers too).
It's easy to use and here is the sample markup once the jQuery plugin is installed.
Sample HTML:
<p class="notSelectable">This text is not selectable</p>
<p> This text is selectable</p>
Sample jQuery:
$(document).ready(function(){
$('.notSelectable').disableSelection();
});
Plugin code:
$.fn.extend({
disableSelection: function() {
this.each(function() {
this.onselectstart = function() {
return false;
};
this.unselectable = "on";
$(this).css('-moz-user-select', 'none');
$(this).css('-webkit-user-select', 'none');
});
return this;
}
});
Per your message comment: I still need to be able to trigger events (notably, touchstart, touchmove, and touchend) on the elements.
I would simply would use a wrapper that is not affected by this plugin, yet it's text-contents are protected using this plugin.
To allow interaction with a link in a block of text, you can use span tags for all but the link and add class name .notSelected for those span tags only, thus preserving selection and interaction of the anchors link.
Status Update: This updated jsFiddle confirms you concern that perhaps other functions may not work when text-selection is disabled. Shown in this updated jsFiddle is jQuery Click Event listener that will fire a Browser Alert for when the Bold Text is clicked on, even if that Bold Text is not text-selectable.
-webkit-user-select:none; wasn't supported on Android until 4.1 (sorry).
I've looked through dozens of pages if similar questions, none of them have any answers, so hopefully this one will be different.
I have a webview, and I do not want the zoom of the view to change from the initial zoom level I have it set to. The only thing which changes the zoom level currently is when a text box is focused.
I need to be able to do this through Java code, not using the viewport meta tag.
Just so I don't have the common responses, I have the following in my code to disable zooming, and the zoom controls:
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setSupportZoom(false);
I'm thinking that a possible solution is to check to see when an onFocus or even an onClick event occurs within the WebView and then zoomOut, but I'm not even sure if that is possible?
Any suggestions would be appreciated.
UPDATE This answer was written almost 6 years ago, with all the new android versions that came since then, this is most likely outdated.
This thing caused a major headache, but finally was solved thanks to setDefaultZoom(ZoomDensity.FAR);
One thing which is important is that onCreate and loadUrl get called before the WebSettings, otherwise it caused a force close situation. Here the ENTIRE code including imports (for the novice Java users)
package com.my.app;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebSettings.ZoomDensity;
import com.phonegap.*;
public class MyDroidActivity extends DroidGap {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.loadUrl("file:///android_asset/www/index.html");
WebSettings settings = appView.getSettings();
settings.setBuiltInZoomControls(false);
settings.setSupportZoom(false);
settings.setDefaultZoom(ZoomDensity.FAR);
}
}
I solved this on HTC phones by adding a WebViewClient with an empty listener for onScaleChanged. My app is PhoneGap, so this is what it looks like, but adding the listener should look the same in a non-PhoneGap app:
public class Main extends DroidGap {
private class NoScaleWebViewClient extends GapViewClient {
public NoScaleWebViewClient(DroidGap ctx) {
super(ctx);
}
public void onScaleChanged(WebView view, float oldScale, float newScale) {
Log.d("NoScaleWebViewClient", "Scale changed: " + String.valueOf(oldScale) + " => " + String.valueOf(newScale));
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.init();
setWebViewClient(appView, new NoScaleWebViewClient(this));
// disables the actual onscreen controls from showing up
appView.getSettings().setBuiltInZoomControls(false);
// disables the ability to zoom
appView.getSettings().setSupportZoom(false);
appView.getSettings().setDefaultZoom(ZoomDensity.FAR);
appView.setInitialScale(100);
}
}
Strangely, the onScaleChange listener never gets called -- by listening for the zoom, it blocks the zoom from happening. I've found that I need all the other calls (setSupportZoom, setDefaultZoom, setInitialScale) in order for this to work, and removing any of them reverts to the old, buggy behavior.
I had the same trouble. I needed to find a way to scale content of webview to exact value, everything worked fine until user starts to input text. There are methods that work on relatively new devices android 4.0+ but fails on old ones. The only way that works everywhere is setting the zoom value not in Java but in viewport like this
<meta name="viewport" content="initial-scale=.80; maximum-scale=.80; minimum-scale=.80;" />
It works on every device I tested.
Did you try to disable the user-scalable in the viewport tag? Not sure if that will work for you, but it works for me. I did not need to do anything on the java side.
<meta name="viewport" content="user-scalable=no, width=device-width" />
I have encountered this problem too, and I solved it like this:
myWebview.getSettings().setDefaultZoom(ZoomDensity.FAR);
It's runing normally on Sumsung Galaxy Tab. I hope this will help you.
The WebView has one special "thing", which I think it will trigger many questions and answers here. What happens is, that when an URL is loaded, the default Android Browser kicks in through an Intent to handle this. The zooming takes part in this browser, not in your Webview.
Solution: You need to add a WebviewClient to tell Android that you handle the browsing yourself. An example:
// Use WebView and disable zooming
public class MyWebView extends Activity {
// nested class
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true
}
}
private WebView mWebView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebViewClient(new HelloWebViewClient());
mWebView.setInitialScale(500); // added after user comment
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setSupportZoom(false);
mWebView.loadUrl("http://www.google.com");
}
}
My main.xml looks like this
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
This code disabled zooming on my HTC Desire running Android 2.2. Tapping into HTML Input fields makes no difference.
The whole topic of WebView/HelloWebViewClient as well as an important hint to handle the "Back" button correctly is documented in Hello Views, Web View. It should be required reading for anybody who uses WebView.
I believe you can set the zoom level with WebView.setInitialScale method. It takes an int as scale so I guess you would want to do something like myWebView.setInitialScale(100).
This issue has been fixed by a firmware update on HTC devices, it was (apparently) being caused by the Sense UI overriding default Android functionality incorrectly.
It is very difficult to provide information on exactly when this was corrected, however my web application no longer zooms when a text box is clicked on any HTC device with the latest firmware.
The following two lines of code will disable the "zoom" aspects of an android webview:
// disables the actual onscreen controls from showing up
mWebView.getSettings().setBuiltInZoomControls(false);
// disables the ability to zoom
mWebView.getSettings().setSupportZoom(false);
This was headache for me too, but fortunately I have found this article: How to stop zoom in on input focus on mobile devices.
Set font size of the text in the input element to 16px (or more) in the css file.
input {
font-size: 16px;
}
It is rather hack, but if nothig else works ...