SwipeRefreshLayout手动显示刷新动画

简述

比如说要服务器取新闻数据,界面将会一个列表形式,支持下拉刷新功能。通常做法都会在进入界面时,把下拉刷新的动画显示出来,数据获取成功后隐藏刷新动画,这样的做法很普遍。然后在Google在supperV4包也添加一个支持下拉刷新控件SwipeRefreshLayout后, 只能说小小惊喜,好不好用自己体会咯。那么今天讲手动调用显示刷新动画。

分析源码

下拉刷新数据完成后调用setRefreshing(false)停止刷新动画,那么是不是参数为true就是显示动画呢?可恶的SwipeRefreshLayout在onCreate()中调用setRefreshing(true)不显示刷新动画,拉门奇怪看看源码吧

    public void setRefreshing(boolean refreshing) {
        if (refreshing && mRefreshing != refreshing) {
            // scale and show
            mRefreshing = refreshing;
            int endTarget = 0;
            if (!mUsingCustomStart) {
                endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop);
            } else {
                endTarget = (int) mSpinnerFinalOffset;
            }
            setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop,
                    true /* requires update */);
            mNotify = false;
            startScaleUpAnimation(mRefreshListener);
        } else {
            setRefreshing(refreshing, false /* notify */);
        }
    }

可以看到上面源码中调用了setTargetOffsetTopAndBottom方法来偏移下拉动画的位置,我们打个断点瞧瞧,额,setRefreshingmCurrentTargetOffsetTop竟然是0

非UI线程列队

但继续断点到setTargetOffsetTopAndBottom中,mCurrentTargetOffsetTop值为192了,既然有值为什么手动调用显示不了动画呢?继续跟踪!发现在onMeasure中值为负数了

Paste_Image.png

来看看onMeasure方法,mCurrentTargetOffsetTop为-140,我去这值肯定是跑到手机屏幕外面显示了,哈哈~都跟到这里了,再跟踪一下吧onLayout

Paste_Image.png

onLayout还调用了动画圆圈控件mCircleView.layout

Paste_Image.png

经过刚才的断点跟踪,源码调用顺序如下:
setRefreshing(boolean refreshing) -> setTargetOffsetTopAndBottom - >onMeasure -> onLayout -> onMeasure -> onLayout
这样看来知道原因了吧,在setTargetOffsetTopAndBottommCurrentTargetOffsetTop是有值的,可后面又执行了onMeasure导致mCurrentTargetOffsetTop为负数

实现方式一

那我们是不是可以这样想,等onLayout绘制个控件的位置完成后,最后执行我们调用的setRefreshing(true)呢?这有点思路了,可以用post(Runnable action)的方法把setRefreshing(true)加入到UI线程列队中,所以用下面代码来试试,惊喜动画有显示了。成功!

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final SwipeRefreshLayout mSwipeRefreshLayout =
                (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);

//        mSwipeRefreshLayout.setRefreshing(true);

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

    }

再看断点后执行顺序
onMeasure -> onLayout -> setRefreshing(boolean refreshing) -> setTargetOffsetTopAndBottom -> onMeasure -> onLayout
那么问题来了,后面不还是执行了onMeasure吗?是,是执行了,但关键代码在mOriginalOffsetCalculated这个变量,第一次执行onMeasure后,此变量已经为true,所以第二onMeasure不会进入if分支中,源码如下

Paste_Image.png

实现方式二

正如onMeasure中那段给mCurrentTargetOffsetTop赋值的代码块,如果能让mUsingCustomStart为true的话,那么也能不进入if分支,那么我们就找找mUsingCustomStart在何时有赋值为true的方法,功夫不负有心人,在setProgressViewOffset方法中有,并且看方法名字的意思可以知道,设置进度视图偏移,mSpinnerFinalOffset = end应该是偏移结束位置。

Paste_Image.png

尝试用以下代码试试,果然这样也是成功的

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final SwipeRefreshLayout mSwipeRefreshLayout =
                (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
        mSwipeRefreshLayout.setProgressViewOffset(false, 0, 52);
        mSwipeRefreshLayout.setRefreshing(true);

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

    }

总结

二种方式手动显示下拉动画

  • UI线程列队
	    mSwipeRefreshLayout.post(new Runnable() {

        @Override
        public void run() {
            mSwipeRefreshLayout.setRefreshing(true);
        }
    });
  • 偏移
mSwipeRefreshLayout.setProgressViewOffset(false, 0, 100);
mSwipeRefreshLayout.setRefreshing(true);

最后奉上一个我自己封装的下拉刷新库,封装的不妥地方欢迎提出宝贵意见

欢迎关注公众号,每天为您推送“人生感悟、说话技巧、职场规则、职场成长”
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易家兴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值