blavi
blavi

Reputation: 531

SwipeRefreshLayout refresh animation doesn't stop

I've implemented a fragment which has a SwipeRefreshLayout as content view. Refresh animation is triggered at onRefresh but it never stops even if setRefreshing is set to false after retrieving the data from server.

    @Override
public void onRefresh() {
    handler.post(refreshing);
}


private final Runnable refreshing = new Runnable(){
    public void run(){
        try {
            if(isRefreshing()){
                handler.postDelayed(this, 1000);
            }else{
                swipeLayout.setRefreshing(false);
                mainActivity.forceUpdate();
                setLayout();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
};

private boolean isRefreshing(){
    return swipeLayout.isRefreshing();
}

Upvotes: 17

Views: 40399

Answers (8)

Favour Felix Chinemerem
Favour Felix Chinemerem

Reputation: 1408

If you use Kotlin, you can do this with Coroutines.

Where binding.dashboardRefresh is my SwipeRefreshLayout.

    //Refresh the info on Swipe-Refresh
    binding.dashboardRefresh.run {
        setOnRefreshListener {
            menuViewModel.getFields()
            val workerScope = CoroutineScope(Dispatchers.IO)
            workerScope.launch {
                delay(3000)
                isRefreshing = false
            }
        }
    }

Upvotes: 0

slprog1
slprog1

Reputation: 71

Don't like Listeners. I do think if you are coding in c# - you have to follow its paradigms. One of those is events. MvxSwipeRefreshLayout has event called Refresh. And what you can do in its handler is to do some stuff that takes some time, like await for it, and then set Refreshing to false

    private async void SwipeToRefreshControl_Refresh(object sender, EventArgs e)
    {
        await ...some stuff here...
        (sender as MvxSwipeRefreshLayout).Refreshing = false;
    }

Upvotes: 0

Rejinderi
Rejinderi

Reputation: 11844

Make sure your listener is set.

mSwipeRefreshLayout = findViewById(R.id.swiperefresh);
mSwipeRefreshLayout.setOnRefreshListener(this); // Important

Upvotes: 0

Ehsan Rafique
Ehsan Rafique

Reputation: 41

if you want to stop loading animation when page is loaded then you have to find first that when page is completely loaded in Webview.

Here is Complete code for load a page in Webview and then stop loading animation after complete page loading.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_web_view);


    final WebView wvSocialMediaPage = findViewById(R.id.wv_social_media_page);
    wvSocialMediaPage.setWebViewClient(new CustomWebViewClient());
    WebSettings webSetting = wvSocialMediaPage.getSettings();
    webSetting.setJavaScriptEnabled(true);
    webSetting.setDisplayZoomControls(true);
    wvSocialMediaPage.loadUrl("https://facebook.com");

    swipeRefreshLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipe_container);
    swipeRefreshLayout.setOnRefreshListener(
            new SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                    wvSocialMediaPage.reload();
                }
            }
    );
}



    private class CustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        swipeRefreshLayout.setRefreshing(false);
    }
}

onPageFinished will find when page is loaded Successfully then stop animation.

Upvotes: 3

iftach barshem
iftach barshem

Reputation: 91

In my case I did

mSwipeRefreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    mSwipeRefreshLayout.setRefreshing(true);
                }
            });

twice. Then, it is not removed by

mSwipeRefreshLayout.setRefreshing(false);

Upvotes: 3

Rishabh Srivastava
Rishabh Srivastava

Reputation: 3745

This will remove the animation :

mSwipeRefreshLayout.setRefreshing(false);

Upvotes: 16

user4470672
user4470672

Reputation: 117

Use setRefreshing(false) in the UI thread.

Try this:

Handler mHandler = new Handler();//In UI Thread

...

mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
        swipeLayout.setRefreshing(isRefreshing);
    }
}, delayTime);

Upvotes: 6

JozeRi
JozeRi

Reputation: 3429

well, of course it's not stopping to refresh, look at your loop.

if(isRefreshing()){
    handler.postDelayed(this, 1000);
}else{
    swipeLayout.setRefreshing(false);
    mainActivity.forceUpdate();
    setLayout();
}

basically you are never stopping it, the "swipeLayout.setRefreshing(false);" is never called, since the condition it needs is (isRefreshing()) to be false, so it doesn't make any sense, you will always get a true value from "isRefreshing()" since you're never telling it to stop. setRefreshing to false based on the boolean value of isRefreshing is wrong in my opinion, you shouldn't rely on it, you should be the one to decide when you want to stop the refresh state.

usually PullToRefresh is used to get new data from server. so basically I would recommend inserting this check right where you get an answer from your server :

if (swipeLayout.isRefreshing()) {
     swipeLayout.setRefreshing(false);
}

because once you get your new data from the server, that's when you need to stop refreshing.

EDIT - added a full code example

protected SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        retrieveDocuments();
    }
};

public void retrieveDocuments() {
//some code, server call

//onCompletion is your server response with a success
@Override
public void onCompletion(String result) {

    if (mSwipeRefreshLayout.isRefreshing()) {
       mSwipeRefreshLayout.setRefreshing(false);
    }
}

}

Upvotes: 27

Related Questions