SwipeRefreshLayout如何在程序中触发

72

有没有办法在程序中触发 SwipeRefreshLayout?动画应该会开始,从 OnRefreshListener 接口传来的 onRefresh 方法也应该被调用。


5
好的,那似乎是不可能的。在我的情况下,我必须调用 mSwipeRefreshLayout.setRefreshing(true); 并新建一个我的 AsyncTask 的实例,然后手动执行它。当然,我把它们放在一个名为 doRefresh() 的方法中,在 onRefresh() 中调用 doRefresh() - Xiao Liang
可能是如何在Android中触发SwipeRefreshLayout?的重复问题。 - opticod
@opticod,一个比“可能”的重复问题更早被提出的问题怎么会是一个重复问题呢? - Niklas
7个回答

149

如果你正在使用5.0中引入的新的swipeRefreshLayout

enter image description here

如上图所示,你只需添加以下代码即可通过编程方式触发swipe refresh layout:

工作

在Java中:

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

Kotlin中的单例模式:

mSwipeRefreshLayout.post { mSwipeRefreshLayout.isRefreshing = true }

不能工作

如果你在Java中简单地调用:

 mSwipeRefreshLayout.setRefreshing(true);

或者在 Kotlin 中

 mSwipeRefreshLayout.isRefreshing = true

添加上述代码行不会触发圆形动画,它只是在UI线程中引入一定的延迟,以便在UI线程中显示圆形动画。

调用mSwipeRefreshLayout.setRefreshing(true)不会执行OnRefreshListener

为了停止循环加载动画,请调用mSwipeRefreshLayout.setRefreshing(false)


我喜欢文档中没有提到这一点吗?我一直在遇到无尽的问题,就是加载符号不显示。是否可以从 UI 线程调用 .setRefreshing(false) - Zapnologica
@Zapnologica:是的,你可以这样做。我是在onRefresh()触发的AsyncTask的onPostExecute中调用它的。 - AgentKnopf
16
@Ramz 我尝试了你的代码片段——旋转器看起来是正常显示的,但与你所提到的不同,当我像你一样手动调用setRefreshing (true)时,我的Fragment中实现的onRefresh回调并没有被调用(我使用的是摩托罗拉Moto X 2014 Android 5+)。因此,我必须将旋转器设置为正在刷新,并手动调用onRefresh回调来执行我的刷新代码。 - AgentKnopf
13
mSwipeRefreshLayout调用setRefreshing(true)后,OnRefreshListener不会被执行,需要修复该问题。 - yat0
3
我认为这是SwipeRefreshLayout中的一个错误。在该类中,有一个名为setRefreshing(boolean refreshing, boolean notify)的私有方法,它允许您控制是否“通知”您的监听器,但setRefreshing(boolean refreshing)将“false”传递给此私有方法,这就是为什么我们的监听器从未被调用的原因。 - hac.jack
相关的Android跟踪问题:https://code.google.com/p/android/issues/detail?id=77712。简而言之:一旦支持库24发布,`post`就不再需要了。 - Marc Plano-Lesay

29

为了触发SwipeRefreshLayout,我尝试了这个解决方案:

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();
        }
    };

现在的关键部分:

swipeLayout.post(new Runnable() {
@Override public void run() {
     swipeLayout.setRefreshing(true);
     // directly call onRefresh() method 
     swipeRefreshListner.onRefresh();
   }
});

1
正如hac.jack在先前的回答评论中提到的那样,SwipeRefreshLayout似乎存在一个bug。有一个内部方法setRefreshing(boolean refreshing, boolean notify)被setRefreshing(booling refreshing)调用。默认情况下,notify参数设置为false,因此OnRefreshListener永远不会更新。这个答案是正确的,可以更新监听器。 - Zac
swipeRefreshLayout.setOnRefreshListener( new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { Log.i(TAG, "从SwipeRefreshLayout调用onRefresh"); // 此方法执行实际的数据刷新操作。 // 当完成操作时,该方法调用setRefreshing(false)。 FetchData(); } } ); - Goodlife

3
只需创建一个 SwipeRefreshLayout.OnRefreshListener 并在需要时调用其函数 onRefresh():
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);

现在,每当您想手动调用它时,只需通过监听器调用即可。
refreshListener.onRefresh();

1

有点晚了,但是你不需要启动一个Runnable来完成这个任务。你可以在onCreate或者其他你想要刷新的地方直接触发刷新并且直接调用你的onRefresh方法:

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
    }
}

0
binding.swipeRefreshLayout.setRefreshing(true); // show loading 
binding.swipeRefreshLayout.post(this::updateUI); // call method
binding.swipeRefreshLayout.setOnRefreshListener(this::updateUI); // call method

3
虽然这段代码片段可能解决了问题,但加上一些解释真的有助于提高您的帖子质量。请记住,您正在回答未来读者的问题,而这些人可能不知道您提出的代码建议的原因。同时也请尽量避免过多的注释,这会降低代码和解释的可读性! - Rohan Khude

-1
您可以在程序中调用 onRefresh() 方法,然后在该方法内部开始动画(如果它尚未启动)。请参见以下内容:
@Override
public void onRefresh() {
    if (!mSwipeRefreshLayout.isRefreshing()) mSwipeRefreshLayout.setRefreshing(true);
    //TODO
}

-2

只是为了强制添加这两个以启用滑动手势

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();
        }
    }
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接