Android——調(diào)用SwipeRefreshLayout.setRefreshing(true),刷新指示器不顯示

引言

前段時(shí)間在網(wǎng)上又看到小伙伴提出SwipeRefreshLayout的指示器不能顯示的問(wèn)題,該問(wèn)題的出現(xiàn)情景是在Activity或者Fragmen的onCreate方法中直接調(diào)用SwipeRefreshLayout.setRefreshing(true)。

其實(shí)這個(gè)問(wèn)題我在14年底的時(shí)候就遇到過(guò)了,后來(lái)在android issues上找到解決方案。本來(lái)不想寫,后來(lái)想想時(shí)間過(guò)去兩年了,Google還沒對(duì)這個(gè)bug進(jìn)行fix,那倒不如根據(jù)那個(gè)android issues做一個(gè)整理幫助更多未找到原因和解決方案的小伙伴們。

原因

在SwipeRefreshLayout.onMeasure()之前,調(diào)用SwipeRefreshLayout.setRefreshing(true)。

解決方案

  • 很簡(jiǎn)單,那就是在SwipeRefreshLayout.onMeasure()之后,調(diào)用SwipeRefreshLayout.setRefreshing(true)。
  • 我把解決方案按照調(diào)用方式簡(jiǎn)單的分為兩類:主調(diào)和回調(diào)。

主調(diào)

Handler延遲時(shí)間執(zhí)行,這個(gè)方案不好,因?yàn)檠舆t時(shí)間很難有一個(gè)準(zhǔn)確數(shù)據(jù),確保在任何機(jī)器上都是可行和完美的。

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        initiateRefresh();
    }
}, 1000); // 時(shí)間可以按自己需要設(shè),不一定是1秒

感謝無(wú)奈的凍魚提供的意見,使用Handler.post(runnable)。 那么為什么Handler.post(runnable)比較好呢?

原因非常簡(jiǎn)單,因?yàn)閍ctivity的onCreate()生命周期方法在調(diào)用setContentVIew()后,UI消息隊(duì)列會(huì)包含繪制view的消息(view的繪制流程——measure,layout,draw),而UI消息隊(duì)列又是按順序執(zhí)行的,所以這時(shí)候handler.post發(fā)出的消息會(huì)后執(zhí)行,因此就相當(dāng)于在view繪制完成后執(zhí)行

通過(guò)設(shè)置指示器的偏移間接地調(diào)用onMeasure():

TypedValue typed_value = new TypedValue();
getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, typed_value, true);
swipeRefreshLayout.setProgressViewOffset(false, 0, getResources().getDimensionPixelSize(typed_value.resourceId));

SwipeRefreshLayout.setProgressViewOffset()源碼:

public void setProgressViewOffset(boolean scale, int start, int end) {
    mScale = scale;
    mCircleView.setVisibility(View.GONE);
    mOriginalOffsetTop = mCurrentTargetOffsetTop = start;
    mSpinnerFinalOffset = end;
    mUsingCustomStart = true;
    mCircleView.invalidate();// onMeasure()就是由此觸發(fā)
}

回調(diào)

重寫SwipeRefreshLayout的onMeasure()和setRefreshing():

private boolean mMeasured = false;
private boolean mPreMeasureRefreshing = false;

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (!mMeasured) {
        mMeasured = true;
        setRefreshing(mPreMeasureRefreshing);
    }
}

@Override
public void setRefreshing(boolean refreshing) {
    if (mMeasured) {
        super.setRefreshing(refreshing);
    } else {
        mPreMeasureRefreshing = refreshing;
    }
}

監(jiān)聽OnGlobalLayoutListener:

private class OnLayoutReadyListener implements OnGlobalLayoutListener {
        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
            if (!mLayoutReady) {
                mLayoutReady = true;
                setRefreshing(mPreLayoutReadyRefreshing);
            }
        }
    }

好消息

經(jīng)過(guò)兩年的時(shí)間后,該issues終于反饋到Android開發(fā)團(tuán)隊(duì):


屏幕快照 2016-03-03 17.11.29.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容