When the page with the WebView first loads, sometimes images are missing or displayed incorrectly. If I reload the page the WebView always displays perfectly. I know everyone will first think I set javascript after loadUrl, but that isn't true.
In onCreate I have:
learnWebView = (WebView)findViewById(R.id.learnWebView);
learnWebView.setWebViewClient(new WebViewClient());
learnWebView.getSettings().setJavaScriptEnabled(true);
Then later in the function called after onCreate I have:
learnWebView.loadUrl("myurl");
And yes, I know that the function with loadUrl is called after onCreate every time.
Please try this instead of your way, that is a bad practice:
learnWebView.post(new Runnable() {
#Override
public void run() {
learnWebView.loadUrl("myurl");
}
});
Or this, in case the first one wont work:
learnWebView.postDelayed(new Runnable() {
#Override
public void run() {
learnWebView.loadUrl("myurl");
}
}, 500);
Hope this helps.
Look at onViewAttachedToWindow.
You should process your logic in javascript only after onViewAttachedToWindow fired.
I met the same issue. not sure if it is the same case as yours. I spent more than 3 days and actually found the cause it that another WebView object calls pauseTimers() for saving some CPU performance which actually " Pauses all layout, parsing, and JavaScript timers for all WebViews."
Related
So i have a program that loads an image and a quote of text from a remote server in a background thread. i have a countdown that after 10 seconds loads a new image and a new quote from the remote server. However, when a connection is slow content is sometimes loaded halfway through the countdown, so i am looking for a way to start the countdown only after the content have been loaded.
From my searching i have found webView.setWebViewClient as a what seems to be a way of doing this by placing the timer.start in the onPageFinished method.
i believe i had a hard time phrasing my question to return a useful solution to my problem, so i am asking here hoping someone more knowledgeable could help me find if the webView method is the way to go, or if there is a more efficient way of solving my problem?
You answered yourself :) In case you are loading the content into the WebView, overriding onPageFinished method of WebViewClient is the way to go.
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
webview.reload();
}
}, 10 * 1000);
}
});
I have a view that contains a user's drawing. When clicking a 'play' button I want to have a loop that draws the image from start to finish.
In attempting to do this I basically have a loop inside of an onClickListener for the play button that essentially invalidates the view, waits, sets the next set of points and invalidates again.
The problem is that the image doesn't actually redraw until after the entire image is draw. So essentially nothing happens and then it's all of a sudden done. After doing some research, my assumption is that invalidate is telling the main UI thread to redraw when it gets time, but it's already hung up on dealing with the listener, so it doesn't actually draw until the loop is finished. I've tried calling onDraw directly, using postInvalidate, and just about any other ridiculous thing I can think of, but I'm not sure how to get this to work.
Here are some code snippets:
In my PaintActivity(Which has a PaintAreaView)
The scrubber indicates the progress of the drawing. The first to lines in onProgressChanged works when I manually use the seek bar, but not when pressing play, which is why I tried adding all the extras.
_scrubber.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
_paintAreaView.setPointsToDraw(_scrubber.getProgress());
_paintAreaView.invalidate();
_mainViewGroup.invalidate();
_paintAreaView.postInvalidate();
_mainViewGroup.postInvalidate();
_paintAreaView.drawPoints(_paintAreaView.getCanvas());
_paintAreaView.invalidate();
}...
My Play Button stuff:
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
playDrawing();
...
}
});
private void playDrawing()
{
int endPoint = getPaintPointCount();
while(_scrubber.getProgress() < endPoint)
{
_scrubber.incrementProgressBy(1);
try{
Thread.sleep(10);
}catch(InterruptedException e)
{
Thread.currentThread().interrupt();
}
//_paintAreaView.setPointsToDraw(_scrubber.getProgress());
//_paintAreaView.invalidate();
//_mainViewGroup.invalidate();
if(_isPaused)
break;
}
}
I'm not a huge fan of using that sleep, but I've struggled with other solutions and that's my next thing to research. But for this question, incrementing the progress bar does successfully call onProgressChanged, but again it just isn't drawing the view until it's out of that play button click listener.
If I have to wait until I'm out of the listener to get this to work, I'm new enough that I'm not sure how I would approach that.
Sorry for my bad code, any help is much appreciated to help me understand what's happening here and what I need to understand to get this to work.
Thank you!
I got it to work, I'm not sure if all I did was necessary, but here are the changes I made based on my Main UI thread theory being the problem.
I created a class Thread member variable:
private Thread _drawThread;
In onCreate():
_drawThread = new Thread(){
public void run(){
playDrawing();
}
};
play Button onClick:
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
_drawThread.start();
}
});
Seems to be doing just what I want! Except the app crashes the second time I hit play :) From here I don't think it'll be to bad to figure out that issue though.
EDIT-----
Creating the Thread in my play button onClickListener instead of having it be a member variable fixed the crashing. I incorrectly assumed the thread would be destroyed as soon as the listener went out of scope on the main thread, but I guess that's not the case.
I want to display a progress bar while the WebView is loading. I am hiding it on OnPageFinished(), but this is too early. The Webview is still rendering the image.
The WebView documentation states: "When onPageFinished() is called, the rendering picture may not be updated yet. To get the notification for the new Picture, use onNewPicture(WebView, Picture)."
However, OnNewPicture and the PictureListener interface is deprecated and obsolete. Is there another way to know that the rendering is complete?
Unfortunately, I have found that there is no event or mechanism to truly know when the page is completely loaded and finished rendering.
How about creating a custom WebChromeClient and overriding its onReceivedIcon() or onProgressChanged() methods. The onReceivedIcon() will be triggered once the favIcon is loaded and and using the onProgressChanged(), you can enquire the progress of the webview loading. I hope this helps
Please refer to this code snippet
webView.setWebChromeClient(new CustomWebChromeClient());
You can use onProgressChanged or onReceivedIcon whatever that suits your needs.
public class CustomWebChromeClient extends WebChromeClient {
#Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress==100) {
progressBar.setVisibility(View.GONE);
progressBar.setProgress(newProgress);
}
}
#Override
public void onReceivedIcon(WebView view, Bitmap icon) {
// icon received here
super.onReceivedIcon(view, icon);
}
}
I think you can add and execute JavaScript function at the end of body tag of your web page to call your JavaScript interface function to hide the progress bar. But, beware of enabling JavaScript on your WebView.
I'm suffering same problem, but there is no way to know the timing.
The only way I use is to give enough room for the rendering completion by postDelayed().
In my case 200ms is enough if u don't use heavy contents more than 200K in text.
I'm trying to take a screenshot of content of my WebView. I creare a bitmap and then create canvas from this bitmap, then I call method drawPage(canvas) inside onPageFinished() (that is a callback from WebChromeClient), but inside onPageFinished() webView still hasn't loaded content, so I see just black page at first, and then I see previous pages(because when I call it second time previous pages are loaded to webView). How could I deal with this problem? I can solve it using hadlers with some delay, but I think there should be better way to do this.
Thanks for help.
I don't think I understand the problem, but are you asking how to trigger an event on a WebView loading a page? Could you create a WebView client and override the onPageCompleted()?
private WebViewClient viewClient {
#Override
public boolean onPageFinished(WebView view, String url) {
//here you can run your Bitmap creating code
return true;
}
}
YourWebView.setWebViewClient(viewClient);
Is this what your looking for?
I apologize for this, and I am sure it's a very rookie question... but I am still trying to grasp java and how everything works (I'm surprised I made it this far.)
I have a TextView inside of a ScrollView and I am trying to get it to focus on the bottom entry each time a new entry is added.
I have this in the code:
getScrollView().post (new Runnable() {
#Override
public void run() {
getScrollView().fullScroll(ScrollView.FOCUS_DOWN);
}
});
that is inside the
public void onClick(View src) {
switch(src.getId()){
case R.id.buttonOk:
(So that when I click ok, it will focus to the bottom.)
now.. I am getting this error: The method getScrollView() is undefined for the type
do i need to call out the name of the scroll view within that first set of code, android:id="#+id/scrollView1"
Again, I am sorry I am so confused on this. I am obviously not getting something right here. Any help is greatly appreciated.
Thanks
you can used this.
scrollview=((ScrollView) findViewById(R.id.scrollview));
scrollview.post(new Runnable() {
#Override
public void run() {
scrollview.fullScroll(ScrollView.FOCUS_DOWN);
}
});
A couple things:
To get access to the view from code, you use (ScrollView)findViewById(R.id.scrollView1) -- getScrollView() doesn't exist, though you can write it using the command I described.
Based on what it sounds like you're trying to do, you might want to look into ListView instead (rather than appending lines to a TextView).