web-dev-qa-db-fra.com

Effet d'en-tête de parallaxe avec RecyclerView

Je souhaite modifier mon ListView dont je dispose actuellement pour utiliser RecyclerView afin de pouvoir utiliser StaggeredGridLayoutManager mais RecyclerView n'a pas la possibilité d'ajouter un en-tête comme ListView.

Habituellement, avec un ListView, je place une vue vide dans l'en-tête, place l'image en dessous de la vue en liste et traduit l'image en bas en faisant défiler la liste pour créer l'effet Parallax.

Donc, sans en-tête, comment puis-je créer le même effet de parallaxe avec RecyclerView?

15
tyczj

Donc, aujourd’hui, j’ai essayé d’archiver cet effet sur une RecyclerView. Je pouvais le faire, mais comme le code est trop important, je vais coller ici mon projet github et expliquer quelques points clés du projet.

https://github.com/kanytu/Android-parallax-recyclerview

Nous devons d’abord examiner getItemViewType dans la classe RecyclerView.Adapter. Cette méthode définit le type de vue dont nous traitons. Ce type sera transmis à onCreateViewHolder et nous pouvons y gonfler différentes vues. Donc ce que j'ai fait était: vérifiez si la position est la première. Si c'est le cas, gonflez l'en-tête, sinon gonflez une ligne normale.

J'ai également ajouté une variable CustomRelativeLayout qui coupe la vue afin que nous n'ayons aucun problème avec les séparateurs et les rangées situées au-dessus de l'en-tête.

À partir de ce moment, vous semblez connaître le reste de la logique sous-jacente. 

Le résultat final était:

enter image description here

MODIFIER:

Si vous devez insérer quelque chose dans l'adaptateur, assurez-vous d'indiquer la position correcte en ajoutant 1 dans la méthode notifyItemChanged/Inserted. Par exemple:

public void addItem(String item, int position) {
    mData.add(position, item);
    notifyItemInserted(position + 1); //we have to add 1 to the notification position since we don't want to mess with the header
}

Une autre modification importante que j'ai faite est la logique de défilement. Le système mCurrentOffset que j'utilisais ne fonctionnait pas avec l'insertion d'élément, car le décalage changerait si vous ajoutez un élément. Alors ce que j'ai fait était:

ViewHolder holder = findViewHolderForPosition(0);
if (holder != null)
  ((ParallaxRecyclerAdapter) getAdapter()).translateHeader(-holder.itemView.getTop() * 0.5f);

Pour tester cela, j'ai ajouté une postDelayed Runnable, démarré l'application, fait défiler l'écran à la fin, ajouté l'élément en position 0 et fais défiler à nouveau. Le résultat était:

enter image description here

Si quelqu'un recherche d'autres effets de parallaxe, il peut consulter mon autre dépôt:

https://github.com/kanytu/Android-parallax-listview

26
Pedro Oliveira

la façon la plus simple de le faire est d'utiliser ci-dessous onScrollListener sans faire appel à aucune bibliothèque.

View view = recyclerView.getChildAt(0);
if(view != null && recyclerView.getChildAdapterPosition(view) == 0)  {
     view.setTranslationY(-view.getTop() / 2);// or use view.animate().translateY();
}

assurez-vous que votre deuxième élément viewHolder a une couleur d'arrière-plan qui correspond à l'arrière-plan du tiroir/de l'activité. si le défilement ressemble à la parallaxe. 

31
k0sh

Pour kotlin, vous pouvez configurer la vue recycleur comme ci-dessous

//setting parallax effects
    recyclerView.addOnScrollListener(object :RecyclerView.OnScrollListener(){
        override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            val view = recyclerView?.getChildAt(0)
            if (view != null && recyclerView?.getChildAdapterPosition(view) === 0) {
                val imageView = view.findViewById(R.id.parallaxImage)
                imageView.translationY = -view.top / 2f
            }
        }
    })
0
Kit

Cette réponse est destinée à ceux qui sont curieux d’ajouter un en-tête de parallaxe à un GridLayoutManager ou un StaggeredGridLayoutManager

Vous voudrez ajouter le code suivant à votre adaptateur dans onBindViewHolder ou onCreateViewHolder

StaggeredGridLayoutManager.LayoutParams layoutParams =
                    (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            layoutParams.setFullSpan(true);
0
Zach