webentwicklung-frage-antwort-db.com.de

Wenn Sie während des Aktualisierens das Fragment mit SwipeRefreshLayout wechseln, friert das Fragment ein, funktioniert jedoch weiterhin

PDATE: Ich dachte, dass es richtig funktioniert. Aber nach einigen Tests gibt es immer noch Probleme * sniff *

Dann habe ich eine einfachere Version gemacht, um zu sehen, was genau passiert, und ich erfahre, dass das erfrischende Fragment, das hätte abgelöst werden sollen, immer noch da ist. Oder genau, die Ansicht des alten Fragments, das dort verblieben ist, oben das neuere Fragment. Da der Hintergrund meiner ursprünglichen App in RecyclerView nicht transparent ist, hat sich herausgestellt, was ich zuvor gesagt habe.

ENDE DER AKTUALISIERUNG


Ich habe ein MainActivity mit folgendem Layout:

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

Das Fragment ContentView, mit dem ich @id/container Ausfülle, ist wie folgt konfiguriert:

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

Und hier ist onCreateView() von 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;
}

Dann schalte ich in MainActivity den anzuzeigenden Inhalt um, indem ich verschiedene ContentView umschalte. Alles sieht gut aus, bis auf eine Sache: Wenn ich ContentView Fragmente während der Aktualisierung durch die Navigationsleiste wechsle, friert der Inhalt ein. Aber eigentlich funktionieren alle Dinge wie gewohnt, außer Sie können es nicht sehen.

72
zlm2012

Nun ... Nach einigem Ringen habe ich dieses Problem schließlich auf eine knifflige Art und Weise selbst gelöst ...

Ich muss nur diese in onPause() hinzufügen:

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

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

Dieses Problem scheint in appcompat 22.1.1 weiterhin aufzutreten. Das Einwickeln des SwipeRefreshLayout in ein FrameLayout löste dies für mich

<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

Zusätzlich zur @ zlm2012-Antwort habe ich festgestellt, dass dieses Problem unter Support Library 21.0.0 reproduziert wurde, aber derzeit bei 21.0.3 behoben zu sein scheint

3
Metaphore

Die Lösung funktioniert, aber ich denke, es ist besser, diese Zeilen in ihre eigene Funktion zu versetzen, wie zum Beispiel:

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

und beim Umschalten des Fragments anrufen.

Fragment prevFrag = fragmentManager.findFragmentById(drawerContainerId);

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

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

Es klappt! Entfernen Sie einfach den Übergang von Ihrem Fragmentersatz. In meinem Fall habe ich Folgendes aus meinem Code entfernt:

.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
1
raphaelbgr

Einstellen clickable="true" im oberen übergeordneten Layout ... Möglicherweise wird das Problem dadurch behoben.

1

Sie können das Problem vorerst vermeiden, indem Sie:

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

Dies hat den zusätzlichen Vorteil, dass die Animation fortgesetzt wird, falls Sie das Fragment nicht wechseln (von einem Menü aus). Es wird auch mit der internen Animation verknüpft, um sicherzustellen, dass die Aktualisierungsanimation nicht zurückgegeben wird, wenn die Netzwerkaktualisierung bereits abgeschlossen ist.

0
Saurabh

Beenden Sie SwipeRefresh, wenn Sie auf den Navigationsmenüpunkt klicken. Es funktionierte.

private void selectItem(int position) {

       mSwipeRefreshLayout.setRefreshing(false);

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