web-dev-qa-db-fra.com

Android: CollapsingToolbarLayout et SwipeRefreshLayout restent bloqués

J'utilise conjointement CollapsingToolbarLayout, RecyclerView et SwipeRefreshLayout:

Xml:

<Android.support.v4.widget.DrawerLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true">

<Android.support.design.widget.CoordinatorLayout
    Android:id="@+id/coordinator_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true">

<Android.support.design.widget.AppBarLayout
    Android:id="@+id/appbar"
    Android:layout_width="match_parent"
    Android:layout_height="@dimen/collapse_toolbar_height"
    Android:fitsSystemWindows="true"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <Android.support.design.widget.CollapsingToolbarLayout
        Android:id="@+id/collapsing_toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:contentScrim="?attr/colorPrimary"
        Android:fitsSystemWindows="true"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            Android:id="@+id/toolbar_image"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:scaleType="centerCrop"
            Android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax" />

        <include
            layout="@layout/activity_main_toolbar"/>

    </Android.support.design.widget.CollapsingToolbarLayout>
</Android.support.design.widget.AppBarLayout>

    <Android.support.v4.widget.SwipeRefreshLayout
        Android:id="@+id/swipe_container"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <cz.yetanotherview.webcamviewer.app.helper.EmptyRecyclerView
            Android:id="@+id/mainList"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:scrollbars="vertical" />
    </Android.support.v4.widget.SwipeRefreshLayout>

    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/floating_action_button"
        Android:layout_height="wrap_content"
        Android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        Android:layout_margin="16dp"
        app:fabSize="mini"
        Android:src="@drawable/ic_action_edit"
        Android:onClick="assignSelectedWebCamsToCategory"/>

    <com.github.clans.fab.FloatingActionMenu
        Android:id="@+id/floating_action_menu"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="bottom|end"
        Android:paddingRight="10dp"
        Android:paddingBottom="8dp"
        Android:paddingLeft="10dp"
        fab:menu_shadowColor="#37000000"
        fab:menu_colorNormal="#DA4336"
        fab:menu_colorPressed="#E75043"
        fab:menu_colorRipple="#99FFFFFF"
        fab:menu_icon="@drawable/fab_add"
        fab:menu_buttonSpacing="10dp"
        fab:menu_labels_textColor="@color/very_dark_grey"
        fab:menu_labels_textSize="14sp"
        fab:menu_labels_colorNormal="@color/white"
        fab:menu_labels_colorPressed="@color/next_grey"
        fab:menu_labels_colorRipple="#99FFFFFF"
        fab:menu_labels_margin="8dp"
        fab:menu_backgroundColor="@color/black_transparent">

        <com.github.clans.fab.FloatingActionButton
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:src="@drawable/ic_action_content_import"
            fab:fab_size="mini"
            fab:fab_label="@string/pref_import_from_server"
            fab:fab_colorNormal="@color/white"
            app:fab_colorPressed="@color/next_grey"
            app:fab_colorRipple="#99FFFFFF"
            Android:onClick="showSelectionDialog"/>

        <com.github.clans.fab.FloatingActionButton
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:src="@drawable/ic_action_content_manually"
            fab:fab_size="mini"
            fab:fab_label="@string/create_manually"
            fab:fab_colorNormal="@color/white"
            app:fab_colorPressed="@color/next_grey"
            app:fab_colorRipple="#99FFFFFF"
            Android:onClick="showAddDialog"/>

        <com.github.clans.fab.FloatingActionButton
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:src="@drawable/ic_action_content_suggestion"
            fab:fab_size="mini"
            fab:fab_label="@string/submit_suggestion"
            fab:fab_colorNormal="@color/white"
            app:fab_colorPressed="@color/next_grey"
            app:fab_colorRipple="#99FFFFFF"
            Android:onClick="showSuggestionDialog"/>

    </com.github.clans.fab.FloatingActionMenu>
</Android.support.design.widget.CoordinatorLayout>

<include
    layout="@layout/activity_main_drawer"/>
</Android.support.v4.widget.DrawerLayout>

Code:

    swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    swipeRefreshLayout.setOnRefreshListener(this);

Comment autoriser l'action d'actualisation par glissement niquement lors de la réduction de la présentation de la barre d'outils: entièrement développé et scrollview (recyclerview) en haut? Le comportement similaire à celui de l'application Google+ ou de la boîte de réception.

Wrong:

enter image description here

Bon:

enter image description here

53
Tomas

Finalement,

J'ai trouvé que SwipeRefreshLayout fonctionne sans aucun "hacks" à partir de la version de la bibliothèque de support technique 23.1.1.

Utilisez simplement dans votre mise en page:

 <Android.support.v4.widget.SwipeRefreshLayout
    Android:id="@+id/swipe_refresh_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/recycler_view"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:scrollbars="vertical" />
</Android.support.v4.widget.SwipeRefreshLayout>

et en code:

SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setColorSchemeResources(R.color.green, R.color.red, R.color.yellow);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
       //Your refresh code here
    }
});

Et n'oubliez pas d'utiliser:

swipeRefreshLayout.setRefreshing(false);

après avoir utilisé votre logique de code;)

24
Tomas

Mise à jour: Ce problème a été résolu dans la dernière version de la bibliothèque de support technique (23.1.1+). Si vous utilisez une version plus ancienne de la bibliothèque de support, mettez à niveau ou continuez la lecture.

Si vous utilisez une version plus ancienne de la bibliothèque de support, ajoutez un écouteur de modification de décalage à votre AppBarLayout pour activer ou désactiver votre balayage pour actualiser la présentation en conséquence. Code supplémentaire disponible ici:

https://Gist.github.com/blackcj/001a90c7775765ad5212

Changements pertinents:

public class MainActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener {
    ...

    private AppBarLayout appBarLayout;
    private SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ...
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.contentView);
        appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);

    }

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
        //The Refresh must be only active when the offset is zero :
        mSwipeRefreshLayout.setEnabled(i == 0);
    }

    @Override
    protected void onResume() {
        super.onResume();
        appBarLayout.addOnOffsetChangedListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        appBarLayout.removeOnOffsetChangedListener(this);
    }
}
90
blackcj

Si je vous ai bien compris, vous souhaitez commencer l’actualisation uniquement après avoir développé la barre d’outils, n’est-ce pas? Il faut donc d'abord ouvrir CollapsingToolbarLayout, puis lancer l'actualisation. Je l'ai géré par le code suivant:

     <Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        xmlns:app="http://schemas.Android.com/apk/res-auto"
        Android:id="@+id/coordinator_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:fitsSystemWindows="true">

        <Android.support.design.widget.AppBarLayout
            Android:id="@+id/app_bar_layout"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:fitsSystemWindows="true"
            Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <Android.support.design.widget.CollapsingToolbarLayout
                Android:id="@+id/collapsing_toolbar"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:fitsSystemWindows="true"
                app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed">

                <LinearLayout
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:orientation="vertical">
                      <!--PUT HERE WHAT EVER YOU WANT TO COLLAPSE, A TOOLBAR, ETC...-->
                </LinearLayout>
            </Android.support.design.widget.CollapsingToolbarLayout>
        </Android.support.design.widget.AppBarLayout>
     <Android.support.v4.widget.SwipeRefreshLayout
        Android:id="@+id/swipe_refresh_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <Android.support.v7.widget.RecyclerView
                Android:id="@+id/recycler_view"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:clipToPadding="false"
                Android:fadeScrollbars="false"
                Android:scrollbars="vertical"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    </Android.support.v4.widget.SwipeRefreshLayout>
</Android.support.design.widget.CoordinatorLayout>   

Et ensuite, dans votre fragment/activité, implémentez-le AppBarLayout.OnOffsetChangedListener (l'actualisation est désormais activée lorsque la barre d'outils est complètement développée):

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        if (collapsingToolbarLayout.getHeight() + verticalOffset < 2 * ViewCompat.getMinimumHeight(collapsingToolbarLayout)) {
            swipeRefreshLayout.setEnabled(false);
        } else {
            swipeRefreshLayout.setEnabled(true);
        }
    }

Remplacez onPause () & onResume () comme dans @blackcj:

  @Override
    public void onResume() {
        super.onResume();
        appBarLayout.addOnOffsetChangedListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        appBarLayout.removeOnOffsetChangedListener(this);
    }

Puis définissez LinearLayoutManager sur votre recyclerView:

    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);

Pour moi, cela a fonctionné comme un charme, d'abord appBarlayout est développé et ensuite seulement swipeRefreshLayout déclenche l'actualisation.

11
hkop

Je devais faire de RecyclerView le principal enfant de SwipeRefreshLayout afin de supprimer le problème à l'aide de Support Library 23.2.0. Impossible de le réparer avec un inclure la mise en page à l'intérieur du SwipeRefreshLayout

<Android.support.v4.widget.SwipeRefreshLayout
        Android:id="@+id/my_swipeRefreshLayout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <!--<include layout="@layout/my_RecyclerView_layout"/> issue for me here -->

        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/my_recyclerView"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent">
        </Android.support.v7.widget.RecyclerView>

    </Android.support.v4.widget.SwipeRefreshLayout>
1
Rensodarwin