在刷新过程中使用SwipeRefreshLayout切换片段时,片段冻结但实际上仍然工作

更新:我认为它工作正常。 但经过一些testing麻烦依然存在*嗅探*

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

更新结束


我有这样的布局的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> 

我用来填充@id/container的片段ContentView被configuration为:

 <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> 

这里是ContentView onCreateView()

 @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碎片,内容就会冻结。 但是实际上所有的东西都照常工作,除非你看不到它。

那么……经过一番苦苦之后,我终于自己解决了这个难题,

我只需要将这些添加到onPause()

 @Override public void onPause() { super.onPause(); ... if (mSwipeRefreshLayout!=null) { mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.destroyDrawingCache(); mSwipeRefreshLayout.clearAnimation(); } } 

这个问题似乎仍然在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> 

除了@ zlm2012的回答,我注意到这个问题在Support Library 21.0.0中被转载了,但现在似乎被修正为21.0.3

解决scheme的工作原理,但我认为最好是把这些行放入自己的函数,如:

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

并在切换片段时调用。

 Fragment prevFrag = fragmentManager.findFragmentById(drawerContainerId); if(prevFrag instanceof SwipeRefreshFragment) { ((SwipeRefreshFragment)prevFrag).terminateRefreshing(); } fragmentManager.beginTransaction().replace(drawerContainerId, fragment).commit(); 

有用! 只是从您的片段replace删除过渡,在我的情况下,我从我的代码中删除以下内容:

 .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) 

在顶级父级布局中设置clickable="true" …可以解决问题。

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

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

这有另外一个好处,就是在你决定不切换片段(来自某个菜单)时重新开始animation。 它还与内部animation绑定,以确保刷新animation在networking刷新已经完成时不会返回。

单击导航菜单项时终止SwipeRefresh。 有效。

 private void selectItem(int position) { mSwipeRefreshLayout.setRefreshing(false); /* Other part of the function */ }