在刷新期间使用SwipeRefreshLayout切换片段时,片段冻结但实际上仍然有效

时间:2014-11-21 08:56:04

标签: android android-fragments android-recyclerview swiperefreshlayout

更新:我认为它运作正常。但经过一些测试后仍然存在问题*嗅探

然后我做了一个更简单的版本,看看到底发生了什么,我知道应该分离的刷新片段仍然留在那里。或者确切地说,旧片段的视图留在那里,位于较新的片段之上。由于RecyclerView的原始应用程序的背景不透明,所以我之前说过的是。

END OF UPDATE


我的MainActivity布局如下:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout"
android:layout_width="match_parent" android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout android:id="@+id/container" android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         If you're not building against API 17 or higher, use
         android:layout_gravity="left" instead. -->
    <!-- The drawer is given a fixed width in dp and extends the full height of
         the container. -->
    <fragment android:id="@+id/navigation_drawer"
        android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent"
        android:layout_gravity="start" tools:layout="@layout/fragment_navigation_drawer" />

</android.support.v4.widget.DrawerLayout>

我用来填充ContentView的片段@id/container配置为:

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

<android.support.v7.widget.RecyclerView
    android:id="@+id/tweet_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grey_300"/>

</android.support.v4.widget.SwipeRefreshLayout>

这是onCreateView()

ContentView
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View inflatedView = inflater.inflate(R.layout.fragment_content, container, false);

    mRecyclerView = (RecyclerView) inflatedView.findViewById(R.id.tweet_list);
    mRecyclerView.setHasFixedSize(false);

    mLinearLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
    mRecyclerView.setLayoutManager(mLinearLayoutManager);

    mTweetList = new ArrayList<Tweet>;
    mAdapter = new TweetAdapter(mTweetList);
    mRecyclerView.setAdapter(mAdapter);
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());

    mSwipeRefreshLayout = (SwipeRefreshLayout) inflatedView.findViewById(R.id.contentView);
    mSwipeRefreshLayout.setOnRefreshListener(
        ...
    );
    return inflatedView;
}

然后在MainActivity中,我通过切换不同的ContentView来切换要显示的内容。除了一件事之外,所有看起来都很好:当我在导航抽屉刷新时切换ContentView个片段,然后内容会冻结。但实际上所有事情都照常工作,除非你看不到它。

7 个答案:

答案 0 :(得分:104)

嗯......经过一番挣扎,我最终以一种棘手的方式解决了这个问题......

我只需要在onPause()中添加这些内容:

@Override
public void onPause() {
    super.onPause();
    ...

    if (mSwipeRefreshLayout!=null) {
        mSwipeRefreshLayout.setRefreshing(false);
        mSwipeRefreshLayout.destroyDrawingCache();
        mSwipeRefreshLayout.clearAnimation();
    }
}

答案 1 :(得分:75)

这个问题似乎仍然发生在appcompat 22.1.1中。在FrameLayout中包装SwipeRefreshLayout为我解决了这个问题

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.widget.SwipeRefreshLayout

    android:id="@+id/contentView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/tweet_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/grey_300" />

</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>

答案 2 :(得分:3)

除了@ zlm2012的回答,我注意到这个问题在支持库21.0.0下重现,但现在似乎在21.0.3修复

答案 3 :(得分:1)

解决方案有效,但我认为最好将这些行放入其自己的功能中,例如:

container

并在切换片段时调用。

public void terminateRefreshing() {
    mSwipeRefreshLayout.setRefreshing(false);
    mSwipeRefreshLayout.destroyDrawingCache();
    mSwipeRefreshLayout.clearAnimation();
}

答案 4 :(得分:1)

有效!只需从您的代码替换中删除转换,在我的情况下,我从代码中删除了以下内容:

.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)

答案 5 :(得分:1)

在顶部父布局中设置clickable="true" ...它可以解决问题。

答案 6 :(得分:0)

目前,您可以通过以下方式避免此问题:

public class FixedRefreshLayout extends SwipeRefreshLayout {

    private static final String TAG = "RefreshTag";
    private boolean selfCancelled = false;

    public FixedRefreshLayout(Context context) {
        super(context);
    }

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

    @Override
    protected Parcelable onSaveInstanceState()
    {
        if(isRefreshing()) {
            clearAnimation();
            setRefreshing(false);
            selfCancelled = true;
            Log.d(TAG, "For hide refreshing");
        }
        return super.onSaveInstanceState();
    }

    @Override
    public void setRefreshing(boolean refreshing) {
        super.setRefreshing(refreshing);
        selfCancelled = false;
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        if(hasWindowFocus && selfCancelled) {
            setRefreshing(true);
            Log.d(TAG, "Force show refreshing");
        }
    }
}

这具有恢复动画的额外优势,因为您决定不切换片段(来自某些菜单)。它还与内部动画相关联,以确保在网络刷新已完成时不会返回刷新动画。