146

非常に単純なレイアウトを使用していますが、フラグメントを呼び出すと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
    }
}
4

14 に答える 14

310

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

mSwipeRefreshLayout.post(new Runnable() {
    @Override
    public void run() {
        mSwipeRefreshLayout.setRefreshing(true);
    }
});
于 2014-11-13T14:18:46.997 に答える
102

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

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

の以前のバージョンでは機能していましたandroid.support.v4が、進行中のバージョン 21.0.0 からは機能せず、2014 年 12 月 10 ~ 12 日にandroid.support.v4:21.0.3リリースされたまま存在します。これが理由です。

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

回避策:

を呼び出すsetProgressViewOffset()SwipeRefreshLayout、レイアウトのサークル ビューが無効SwipeRefreshLayout.onMeasure()になり、すぐに呼び出されます。

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

UPDATEより良い回避策

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

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イシュートラッカーの問題です。修正する必要があることを示すために、賛成票を投じてください。

于 2014-11-11T08:53:37.873 に答える
48

私の解決策はオーバーライドすること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;
        }
    }
}
于 2015-02-24T09:46:46.463 に答える
20
mRefreshLayout.getViewTreeObserver()
                .addOnGlobalLayoutListener(
                        new ViewTreeObserver.OnGlobalLayoutListener() {
                            @Override
                            public void onGlobalLayout() {
                                mRefreshLayout
                                        .getViewTreeObserver()
                                        .removeGlobalOnLayoutListener(this);
                                mRefreshLayout.setRefreshing(true);
                            }
                        });
于 2015-01-27T06:18:10.420 に答える
14

Android サポート ライブラリ 24.2.0 では、この問題は解決されているはずです。 https://developer.android.com/topic/libraries/support-library/revisions.html#24-2-0-bugfixes

于 2016-08-18T09:36:44.560 に答える
4

Based on Volodymyr Baydalka's answer, this is just a small idea that will help you to keep code clean. It deserves a post I believe: you will be able to revert the behavior easily from posting to direct method call, once the bug is fixed.

Write a utility class like:

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

In your code substitute mSwipeContainer.setRefreshing(isRefreshing) by Utils.setRefreshing(mSwipeContainer, isRefreshing): now only one point in the code needs to be changed once the bug is fixed, the Utils class. The method can also be inlined then (and removed from Utils).

There will be usually no noticeable visual difference. Keep in mind though that the pending refresh could keep alive your old Activity instances, holding on the SwipeRefreshLayout in their view hierarchies. If that is a concern, tweak the method to use WeakReferences, but normally you don't block the UI thread anyway, and thus delay gc by a couple of milliseconds only.

于 2015-01-29T14:40:56.427 に答える
1

@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;
    }
}
于 2016-02-28T03:54:38.710 に答える
1

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

アドバイス: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>
于 2015-02-17T00:41:16.243 に答える
0

「com.android.support:appcompat-v7:23.1.1」を使用しています

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

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

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

于 2016-01-15T15:30:56.617 に答える