Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start animation on page load, stop on page loaded

I have a MenuItem in my ActionBar that is a "reload" icon. My Activity has a WebView and I'd like the icon to start animating when the WebView starts loading a webpage and stop when it's finished. This includes when clicking on links in the site that is loaded. What I have so far, works the first time I bring up a webpage, but if I leave the Activity and load another webpage, the "reload" icon seems to double up, or I will get NullReference exception thrown on refreshItem.setActionView(ivRefresh);

enter image description here

Here is my code:

public class Browser extends SherlockFragmentActivity {

    private MenuItem refreshItem;
    private WebView mWebView;

    @Override
    public void onCreate(final Bundle icicle) 
    {
        super.onCreate(icicle);
        setContentView(R.layout.browser);

        mWebView = (WebView)findViewById(R.id.webview);
        mWebView.getSettings().setSupportZoom(true);  
        mWebView.getSettings().setBuiltInZoomControls(true);

        mWebView.loadUrl("http://www.google.com");

        mWebView.setWebViewClient(new WebBrowserClient());

        mWebView.setWebChromeClient(new WebChromeClient() {
            public void onProgressChanged(WebView view, int progress) {

                //if (!isFinishing() && progress == 100 && refreshItem != null && refreshItem.getActionView() != null)
                //{
                //refreshItem.getActionView().clearAnimation();
                //refreshItem.setActionView(null);
                //}
            }
        });         
    }

    private class WebBrowserClient extends WebViewClient {

          @Override
          public void onLoadResource(WebView view, String url) {
              //StartAnimation();
          }

          @Override
          public void onPageStarted(WebView view, String url, Bitmap favicon) {
              StartAnimation();
          }

          @Override
          public void onPageFinished(WebView view, String url) {
            if (refreshItem != null && refreshItem.getActionView() != null)
            {
                refreshItem.getActionView().clearAnimation();
                refreshItem.setActionView(null);
            }
          }

         @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }

    private void StartAnimation() {
        final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final ImageView ivRefresh = (ImageView)inflater.inflate(R.layout.refresh_view, null);

        final Animation rotation = AnimationUtils.loadAnimation(this, R.anim.refresh);
        ivRefresh.startAnimation(rotation);
        refreshItem.setActionView(ivRefresh);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getSupportMenuInflater().inflate(R.menu.menu, menu);

        refreshItem = menu.findItem(R.id.refresh);

        return super.onCreateOptionsMenu(menu);
    }
}

The commented out code is different ways I tried to get it to work.

UPDATE:

After debugging this more, I put a breakpoint in the StartAnimation function and sometimes it's hit up to 7 times in a row and other times it's not. This makes no sense, as, to me, this should be working. Perplexing...

SOLUTION (SORT OF):

Updating the StartAnimation() function to this, seems to fix this issue, but seems more of a duct tape solution:

private void StartAnimation() {
    if (refreshItem != null && refreshItem.getActionView() == null)
    {
        final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final ImageView ivRefresh = (ImageView)inflater.inflate(R.layout.refresh_view, null);

        final Animation rotation = AnimationUtils.loadAnimation(this, R.anim.refresh);
        ivRefresh.startAnimation(rotation);
        refreshItem.setActionView(ivRefresh);
    }
}
like image 212
Kris B Avatar asked May 08 '12 23:05

Kris B


1 Answers

To create a smooth ui-experience, your 'loading wheel' animation should probably start when the user clicks the link - rather than when the new page starts loading - and end when the new page has loaded. This makes the app seem more responsive to the user, and is the behaviour implemented in Dolphin Browser, as an example.

To implement this, you need to listen for the user's link clicks in the WebView. How to do this has already been covered in this answer here on SO:

Detect click on HTML button through javascript in Android WebView

You have to validate that the click is in fact on a link to a new page. You can find the clicked HTML element via WebView's HitTestResult class. This answer on SO gives you the details on how to validate the HitTestResult value:

Get the click event from webpage in my android application

You start your animation from your onClick() method and end it from your WebViewClient's onPageFinished() method and, in case the new page doesn't load, also in onReceivedError().

like image 71
onosendai Avatar answered Oct 13 '22 00:10

onosendai