web-dev-qa-db-fra.com

Lorsque vous changez de fragment avec SwipeRefreshLayout pendant l'actualisation, le fragment se fige mais fonctionne toujours

MISE À JOUR: Je pensais que cela fonctionnait correctement. Mais après quelques problèmes de test existe toujours * sniff *

Ensuite, j'ai fait une version plus simple pour voir ce qui se passait exactement et j'ai appris que le fragment rafraîchissant qui aurait dû être détaché est toujours là. Ou exactement, la vue de l'ancien fragment est restée là, en haut de le fragment le plus récent. Étant donné que l'arrière-plan de RecyclerView de mon application d'origine n'est pas transparent, il s'est avéré ce que j'ai dit auparavant.

FIN DE MISE À JOUR


J'ai un MainActivity avec une disposition comme celle-ci:

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

Le fragment ContentView que j'utilise pour remplir @id/container Est configuré comme:

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

Et voici onCreateView() de 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;
}

Puis dans MainActivity je change le contenu à afficher en changeant différents ContentView. Tout semble bon sauf une chose: lorsque je change de ContentView fragments PENDANT l'actualisation par le tiroir de navigation, le contenu se bloque. Mais en réalité, tout fonctionne comme d'habitude, sauf que vous ne pouvez pas le voir.

72
zlm2012

Eh bien ... Après quelques difficultés, j'ai finalement résolu ce problème par moi-même, d'une manière délicate ...

J'ai juste besoin de les ajouter dans onPause():

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

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

Ce problème semble toujours se produire dans appcompat 22.1.1. Envelopper le SwipeRefreshLayout dans un FrameLayout a résolu cela pour moi

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

En plus de la réponse @ zlm2012, j'ai remarqué que ce problème a été reproduit sous la bibliothèque de support 21.0.0, mais semble être corrigé en ce moment à 21.0.3

3
Metaphore

La solution fonctionne, mais je pense qu'il vaut mieux simplement mettre ces lignes dans sa propre fonction, comme:

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

et appeler lors du changement de fragment.

Fragment prevFrag = fragmentManager.findFragmentById(drawerContainerId);

if(prevFrag instanceof SwipeRefreshFragment) {
    ((SwipeRefreshFragment)prevFrag).terminateRefreshing();
}

fragmentManager.beginTransaction().replace(drawerContainerId, fragment).commit();
1
Huan Xie

Ça marche! Supprimez simplement la transition de votre remplacement de fragment, dans mon cas, j'ai supprimé ce qui suit de mon code:

.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
1
raphaelbgr

Ensemble clickable="true" dans la disposition parent supérieure ... Cela peut résoudre le problème.

1
Bishwajeet Biswas

Pour le moment, vous pouvez éviter le problème en:

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

Cela a l'avantage supplémentaire de reprendre l'animation si vous décidez de ne pas changer le fragment (provenant d'un menu). Il est également lié à l'animation interne pour vous assurer que l'animation rafraîchissante ne revient pas si l'actualisation du réseau est déjà terminée.

0
Saurabh

Arrêtez SwipeRefresh chaque fois qu'un élément du menu de navigation est cliqué. Ça a marché.

private void selectItem(int position) {

       mSwipeRefreshLayout.setRefreshing(false);

       /*
        Other part of the function
       */
}
0
Shashidhara