71

Is there any way to trigger the SwipeRefreshLayout programmatically? The animation should start and the onRefresh method from the OnRefreshListener interface should get called.

Niklas
  • 23,674
  • 33
  • 131
  • 170
  • 5
    Well, that seems to be impossible. In my case, I have to call `mSwipeRefreshLayout.setRefreshing(true);` and new an instance of my AsyncTask then execute it manually. Of course, I put them in a method called `doRefresh()` and in `onRefresh()` it calls `doRefresh()` – Xiao Liang Jul 05 '14 at 15:40
  • Possible duplicate of [How to trigger swiperefreshlayout in android?](http://stackoverflow.com/questions/26513315/how-to-trigger-swiperefreshlayout-in-android) – opticod Dec 19 '16 at 00:24
  • @opticod how is a question that was asked earlier than the 'possible' duplicate a duplicate? – Niklas Dec 19 '16 at 10:55

7 Answers7

149

if you are using the new swipeRefreshLayout intoduced in 5.0 enter image description here

As the image shown above you just need to add the following line to trigger the swipe refresh layout programmatically

Work

in Java:

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

on in Kotlin:

mSwipeRefreshLayout.post { mSwipeRefreshLayout.isRefreshing = true }

NOT work

if you simply call in Java:

 mSwipeRefreshLayout.setRefreshing(true);

or in Kotlin

 mSwipeRefreshLayout.isRefreshing = true

it won't trigger the circle to animate, so by adding the above line u just make a delay in the UI thread so that it shows the circle animation inside the ui thread.

By calling mSwipeRefreshLayout.setRefreshing(true) the OnRefreshListener will NOT get executed

In order to stop the circular loading animation call mSwipeRefreshLayout.setRefreshing(false)

Boken
  • 4,825
  • 10
  • 32
  • 42
Ramz
  • 7,116
  • 6
  • 63
  • 88
  • I love how there is no mention of this in the docs? I have been having endless trouble with the loading sign not displaying. Can one call `.setRefreshing(false)` from the UI thread? – Zapnologica May 25 '15 at 18:29
  • @Zapnologica: Yes you can. I am calling it from onPostExecute of my AsyncTask that was trigger in onRefresh(). – AgentKnopf Jun 04 '15 at 07:47
  • 16
    @Ramz I tried your snippet - the spinner shows but unlike you mentioned, the onRefresh callback implemented by my Fragment is not being called when I manually call setRefreshing (true) like you did (Motorola Moto X 2014 Android 5+). So I have to set the spinner to refreshing and manually call the onRefresh callback to execute my refresh code. – AgentKnopf Jun 04 '15 at 07:51
  • 13
    OnRefreshListener WILL NOT get executed after mSwipeRefreshLayout.setRefreshing(true)... You should fix that – yat0 Aug 28 '15 at 15:04
  • 3
    I think it's a bug in SwipeRefreshLayout, there's a private method in that class called setRefreshing(boolean refreshing, boolean notify) that allows you to control whether to "notify" your listener, but setRefreshing(boolean refreshing) passes "false" down to this private method, that's why our listener never get called. – hac.jack Jan 14 '16 at 00:32
  • Related issue on Android tracker: https://code.google.com/p/android/issues/detail?id=77712. TL;DR: the `post` should not be needed anymore once the support libraries 24 are released. – Marc Plano-Lesay Jun 09 '16 at 08:16
28

In order to trigger SwipeRefreshLayout I tried this solution:

SwipeRefreshLayout.OnRefreshListener swipeRefreshListner = new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            Log.i(TAG, "onRefresh called from SwipeRefreshLayout");
            // This method performs the actual data-refresh operation.
            // The method calls setRefreshing(false) when it's finished.
            loadData();
        }
    };

Now key part:

swipeLayout.post(new Runnable() {
@Override public void run() {
     swipeLayout.setRefreshing(true);
     // directly call onRefresh() method 
     swipeRefreshListner.onRefresh();
   }
});
Min2
  • 10,751
  • 2
  • 19
  • 22
  • 1
    As mentioned in one of the previous answer's comments by hac.jack there appears to be a bug with SwipeRefreshLayout. There's an inner method setRefreshing(boolean refreshing, boolean notify) that's called by setRefreshing(booling refreshing). The notify parameter is set to false by default therefore the the OnRefreshListener is never updated. This answer is correct to get the listener updated. – Zac Mar 07 '16 at 04:56
  • swipeRefreshLayout.setOnRefreshListener( new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { Log.i(TAG, "onRefresh called from SwipeRefreshLayout"); // This method performs the actual data-refresh operation. // The method calls setRefreshing(false) when it's finished. FetchData(); } } ); – Goodlife Sep 07 '16 at 09:22
3

Simply create a SwipeRefreshLayout.OnRefreshListener and call its function onRefresh() whenever needed:

SwipeRefreshLayout srl;
SwipeRefreshLayout.OnRefreshListener refreshListener;

srl = (SwipeRefreshLayout)v.findViewById(R.id.swipeRefreshLayout);

refreshListener = new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
      //Do your stuff here
    }
};
srl.setOnRefreshListener(refreshListener);

Now, whenever you want to call it manually, just call it through the listener

refreshListener.onRefresh();
andrewJames
  • 19,570
  • 8
  • 19
  • 51
1

Bit late to the thread, but you do not need to launch a Runnable to do this. You can simply trigger the refresh and call your onRefresh method directly in onCreate, or wherever you want this to happen:

class MyFragment: SwipeRefreshLayout.OnRefreshListener {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initViews()
    }

    fun initViews() {
        swipe_refresh_layout?.apply {
            setOnRefreshListener(this@MyFragment)
            isRefreshing = true
            onRefresh()
        }
    }

    override fun onRefresh() {
        // Do my refresh logic here
    }
}
Indiana
  • 683
  • 7
  • 18
0
binding.swipeRefreshLayout.setRefreshing(true); // show loading 
binding.swipeRefreshLayout.post(this::updateUI); // call method
binding.swipeRefreshLayout.setOnRefreshListener(this::updateUI); // call method
  • 3
    While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Rohan Khude May 30 '19 at 10:37
-1

You can call onRefresh() method programmatically and then inside the method start the animation if it is not already started. See the following:

@Override
public void onRefresh() {
    if (!mSwipeRefreshLayout.isRefreshing()) mSwipeRefreshLayout.setRefreshing(true);
    //TODO
}
-2

Just to force in add this two to ennable swipe gesture

swipeRefreshLayout.setOnRefreshListener(
    new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            Log.i(TAG, "onRefresh called from SwipeRefreshLayout");

            // This method performs the actual data-refresh operation.
            // The method calls setRefreshing(false) when it's finished.
            FetchData();
        }
    }
);
Linh
  • 57,942
  • 23
  • 262
  • 279
Goodlife
  • 3,822
  • 2
  • 24
  • 23