web-dev-qa-db-ja.com

SwipeRefreshLayout setRefreshing()が最初にインジケーターを表示しない

レイアウトは非常に単純ですが、フラグメントのsetRefreshing(true)onActivityCreated()を呼び出すと、最初は表示されません。

更新するためにプルを行ったときにのみ表示されます。最初に表示されない理由はありますか?

フラグメントxml:

<Android.support.v4.widget.SwipeRefreshLayout
    Android:id="@+id/swipe_container"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <ScrollView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:orientation="vertical">

        </RelativeLayout>


    </ScrollView>
</Android.support.v4.widget.SwipeRefreshLayout>

フラグメントコード:

public static class LinkDetailsFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener {

    @InjectView(R.id.swipe_container)
    SwipeRefreshLayout mSwipeContainer;

    public static LinkDetailsFragment newInstance(String subreddit, String linkId) {
        Bundle args = new Bundle();
        args.putString(EXTRA_SUBREDDIT, subreddit);
        args.putString(EXTRA_LINK_ID, linkId);

        LinkDetailsFragment fragment = new LinkDetailsFragment();
        fragment.setArguments(args);

        return fragment;
    }

    public LinkDetailsFragment() {
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mSwipeContainer.setOnRefreshListener(this);
        mSwipeContainer.setColorScheme(Android.R.color.holo_blue_bright,
                Android.R.color.holo_green_light,
                Android.R.color.holo_orange_light,
                Android.R.color.holo_red_light);
        mSwipeContainer.setRefreshing(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View rootView = inflater.inflate(R.layout.fragment_link_details, container, false);
        ButterKnife.inject(this, rootView);
        return rootView;
    }

    @Override
    public void onRefresh() {
        // refresh
    }
}
139
thunderousNinja

同じ問題に直面した。私の解決策-

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

代わりに、Volodymyr Baydalkaの回答を参照してください。

これらは古い回避策です。

以前はAndroid.support.v4の以前のバージョンで動作していましたが、バージョン21.0.0以降は動作せず、2014年12月10-12日でリリースされたAndroid.support.v4:21.0.3とともに存在します。これが理由です。

setRefreshing(true)SwipeRefreshLayout.onMeasure()の前に呼び出された場合、SwipeRefreshLayoutインジケーターは表示されません。

回避策:

呼び出し setProgressViewOffset() レイアウトの円表示を無効にするSwipeRefreshLayoutで、SwipeRefreshLayout.onMeasure()がすぐに呼び出されます。

mSwipeRefreshLayout.setProgressViewOffset(false, 0,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
mSwipeRefreshLayout.setRefreshing(true);

PDATE Better Workaround

方向が変わるとアクションバーが薄くなるか、アクションバーのサイズを手動で設定したためです。スワイプジェスチャが成功して現在のアクションバーのサイズになった後、プログレススピナーがリセットされるこのビューの上部からのオフセットをピクセル単位で設定します。

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

2014年11月20日更新

ビューの開始後にSwipeRefreshLayoutを表示することがアプリにとってそれほど重要ではない場合。ハンドラーまたは必要なものを使用して、将来のある時点に投稿することができます。

例として。

handler.postDelayed(new Runnable() {

    @Override
    public void run() {
        mSwipeRefreshLayout.setRefreshing(true);
    }
}, 1000);

またはVolodymyr Baydalkaの答えが述べたように。

Android課題トラッカーの issue は次のとおりです。修正する必要があることを示してください。

100
Ahmed Hegazy

私の解決策はSwipeRefreshLayoutをオーバーライドすることです:

public class MySwipeRefreshLayout extends SwipeRefreshLayout {

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

    public MySwipeRefreshLayout(final Context context) {
        super(context);
    }

    public MySwipeRefreshLayout(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    public void setRefreshing(final boolean refreshing) {
        if (mMeasured) {
            super.setRefreshing(refreshing);
        } else {
            mPreMeasureRefreshing = refreshing;
        }
    }
}
46
niks.stack
mRefreshLayout.getViewTreeObserver()
                .addOnGlobalLayoutListener(
                        new ViewTreeObserver.OnGlobalLayoutListener() {
                            @Override
                            public void onGlobalLayout() {
                                mRefreshLayout
                                        .getViewTreeObserver()
                                        .removeGlobalOnLayoutListener(this);
                                mRefreshLayout.setRefreshing(true);
                            }
                        });
20
baoyz

Androidサポートライブラリ24.2.0を使用すると、問題は解決されました。 https://developer.Android.com/topic/libraries/support-library/revisions.html#24-2-0-bugfixes

14
Andrei Buneyeu

Volodymyr Baydalkaの答え に基づくと、これはコードをクリーンに保つのに役立つ小さなアイデアにすぎません。それは私が信じる投稿に値します。バグが修正されると、投稿から直接メソッド呼び出しに振る舞いを簡単に戻すことができるでしょう。

次のようなユーティリティクラスを記述します。

public class Utils
{
    private Utils()
    {
    }

    public static void setRefreshing(final SwipeRefreshLayout swipeRefreshLayout, final boolean isRefreshing)
    {
        // From Guava, or write your own checking code
        checkNonNullArg(swipeRefreshLayout);
        swipeRefreshLayout.post(new Runnable()
        {
            @Override
            public void run()
            {
                swipeRefreshLayout.setRefreshing(isRefreshing);
            }
        });
    }
}

コード内でmSwipeContainer.setRefreshing(isRefreshing)Utils.setRefreshing(mSwipeContainer, isRefreshing)に置き換えます。バグが修正されたら、コード内の1つのポイントのみを変更する必要があります(Utilsクラス)。メソッドをインライン化することもできます(そしてUtilsから削除できます)。

通常、目立った視覚的な違いはありません。ただし、保留中の更新により、ビューの階層でActivityを保持したまま、古いSwipeRefreshLayoutインスタンスを存続させることができることに注意してください。それが懸念される場合は、メソッドを調整してWeakReferencesを使用しますが、通常はUIスレッドをブロックしないため、gcを数ミリ秒だけ遅延させます。

4
Gil Vegliach

また、setRefreshingの前にこのメソッドを呼び出すこともできます。

    swipeRefreshLayout.measure(View.MEASURED_SIZE_MASK,View.MEASURED_HEIGHT_STATE_SHIFT);
swipeRefreshLayout.setRefreshing(true);

それは私のために働きます。

2

@ niks.stack彼の答えに応えて、onLayout()が実行された後、進行状況を表示します。 onMeasure()の直後に使用した場合、オフセットの一部は無視されますが、onLayout()の後に使用した場合はオフセットになります。

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    if (!mLaidOut) {
        mLaidOut = true;
        setRefreshing(mPreLayoutRefreshing);
    }
}

@Override
public void setRefreshing(boolean refreshing) {
    if (mLaidOut) {
        super.setRefreshing(refreshing);
    } else {
        mPreLayoutRefreshing = refreshing;
    }
}
1
mco

Volodymyr Baydalkaに加えて、次のコードも使用します。

swipeContainer.post(new Runnable() {
        @Override
        public void run() {
            swipeContainer.setRefreshing(false);
        }
    });

説明 Volodymyr Baydalkaが提供するソリューションを(フラグメントを使用して)実装しましたが、swipeRefereshの開始後、swipeContainer.setRefreshing(false);を呼び出しても消えることはなかったため、上記のコードを実装して問題を解決しました。これがなぜ起こるのか、これ以上のアイデアは大歓迎です。

よろしく、

'com.Android.support:appcompat-v7:22.2.1'

1
Juni

AppCompatライブラリcom.Android.support:appcompat-v7:21.0.3を使用し、同じアプローチを使用しましたが、うまくいきました。そのため、そのライブラリのバージョンを更新します。

アドバイス:RelativeLayoutは方向をサポートしていません。これはLinearLayoutの属性です。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
                                                 Bundle savedInstanceState) {       
  ViewGroup view = (ViewGroup) inflater.inflate(R.layout.license_fragment, 
           container, false);ButterKnife.inject(this, view);
    // Setting up Pull to Refresh
    swipeToRefreshLayout.setOnRefreshListener(this);
    // Indicator colors for refresh
    swipeToRefreshLayout.setColorSchemeResources(R.color.green, 
                R.color.light_green);
}

レイアウトXML:

<Android.support.v4.widget.SwipeRefreshLayout>

<ScrollView
                    Android:layout_width="match_parent"
                    Android:layout_height="match_parent"
                    Android:paddingBottom="@dimen/activity_margin_vertical"
                    Android:paddingTop="@dimen/activity_margin_vertical">

    <!-- Content -->
</ScrollView>

</Android.support.v4.widget.SwipeRefreshLayout>
1
Jesús Castro

「com.Android.support:appcompat-v7:23.1.1」を使用している

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

以前はswipeRefreshLayout.setRefreshing(true);メソッド内でgetData()を使用していたため、機能していませんでした。メソッド内で動作しない理由はわかりません。

swipeRefreshLayout.setRefreshing(true);はFragmentで一度だけ使用しましたが。

0
Chinmay

私のソリューション(サポートv7なし)-

TypedValue typed_value = new TypedValue();
getTheme().resolveAttribute(Android.R.attr.actionBarSize, typed_value, true);
swipeLayout.setProgressViewOffset(false, 0, getResources().getDimensionPixelSize(typed_value.resourceId));

if(!swipeLayout.isEnabled())
     swipeLayout.setEnabled(true);
swipeLayout.setRefreshing(true);
0
Artrmz

これを試して

mSwipeRefreshLayout.setNestedScrollingEnabled(true);

0
Ashwin H