>更新:我认为它工作正常。但是经过一些测试后,问题仍然存在*嗅探*
然后我做了一个更简单的版本,看看到底发生了什么,我知道应该分离的刷新片段仍然留在那里。或者确切地说,旧片段的视图留在那里,在新片段之上。由于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
片段配置为:
<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 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答案之外,我注意到此问题已在支持库 21.0.0 下重现,但现在似乎已修复在 21.0.3
解决方案有效,但我认为最好将这些行放入其自己的函数中,例如:
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();
有效!只需从片段替换中删除过渡,就我而言,我从代码中删除了以下内容:
.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");
}
}
}
这还有一个额外的优点,即在您决定不切换片段(来自某些菜单)的情况下恢复动画。它还与内部动画相关联,以确保在网络刷新已完成时不会返回刷新动画。
每当单击导航菜单项时终止轻扫刷新。成功了。
private void selectItem(int position) {
mSwipeRefreshLayout.setRefreshing(false);
/*
Other part of the function
*/
}