更新:私はそれが正しく働くと思った。しかし、いくつかのテストのトラブルがまだ存在する* sniff *
次に、より単純なバージョンを作成して正確に何が起こるかを確認し、デタッチするはずのリフレッシュフラグメントがまだ残っていることを知りました。または、正確には、古いフラグメントのビューがそこに残っています上新しいフラグメント。私の元のアプリの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
を切り替えることにより、表示するコンテンツを切り替えます。 1つを除いてすべてが見栄えが良い:ナビゲーションドロワーによる更新中に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の回答に加えて、この問題はサポートライブラリ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");
}
}
}
これには、フラグメントを切り替えないことを決定した場合にアニメーションを再開するという追加の利点があります(一部のメニューから)。また、内部のアニメーションと連携して、ネットワークの更新が既に完了している場合、更新するアニメーションが戻らないようにします。
ナビゲーションメニュー項目がクリックされるたびにSwipeRefreshを終了します。出来た。
private void selectItem(int position) {
mSwipeRefreshLayout.setRefreshing(false);
/*
Other part of the function
*/
}