2017-01-11 5 views
5

ce que je veux réaliserRecyclerView horizontale avec des hauteurs d'éléments variables non emballage correctement

enter image description here

La vue de l'élément doit occuper toute la hauteur de l'élément

enter image description here

Il pourrait soit que la hauteur de l'objet soit inférieure à la hauteur de l'objet le plus haut dans le recyclerview, auquel cas il devrait juste coller au sommet comme dans la capture d'écran ci-dessus.

Le bug que je cours dans

enter image description here

Comme dans la capture d'écran ci-dessus, les vues sont tronquées se.

Ce que j'ai essayé jusqu'à présent

Au départ, je suis allé avec wrap_content sur le recyclerview, maintenant qu'il est pris en charge. Cela n'a pas fonctionné quand aucune des vues visibles à l'écran n'était la plus grande. Cela a du sens dans la façon dont la hiérarchie des vues est présentée. Comment peut-on calculer la hauteur de quelque chose qui n'a pas encore été lié à des données si la hauteur dépend de ces données?

temps Solution: S

Au lieu d'essayer un LayoutManager personnalisé, je suis allé avec ce que je ressentais qu'il fallait faire - la pose sur toutes les vues de l'objet au début de comprendre leur hauteur.

Il y a une barre de progression et une animation qui joue dans la partie supérieure de l'écran pour attirer l'attention de l'utilisateur pendant que tout cela se produit avec la visibilité recycleless définie sur invisible. J'utilise deux choses, une n'a pas suffi - j'ai joint un observateur dans l'appel onViewAttached() de l'adaptateur et j'ai aussi utilisé un écouteur de changement de défilement. Il y a un LinearSnapHelper attaché à la vue recycleur pour s'accrocher à la position adjacente (suivant ou précédent, selon la direction de défilement) lors du défilement.

Dans cette configuration,

  1. Je vais à chaque position dans le recyclerview en utilisant layoutManager.smoothScrollToPosition()
  2. Obtenir la hauteur de vue de l'enfant en utilisant

     View currentChildView = binding.nextRv.getChildAt(layoutManager.findFirstCompletelyVisibleItemPosition()); 
         if (currentChildView != null) { 
          currentChildHeight = currentChildView.getHeight(); 
         } 
    

en défilement changement écoute sur RecyclerView.SCROLL_STATE_IDLE ou en passant la hauteur à l'observateur ci-joint vu ci-dessus dans l'onVie de l'adaptateur wAttachedToWindow()

@Override 
public void onViewAttachedToWindow(BindingViewHolder holder) { 
    if (mObserver != null) { 
     mObserver.onViewAttached(holder.binding.getRoot().getHeight()); 
    } 
} 
  1. Enregistrement d'un maxHeight qui change au maximum de maxHeight et la hauteur de nouvel enfant.

Comme il est évident, c'est moche. De plus, il ne me donne pas la hauteur de la vue actuelle - sur Attaché signifie qu'il est seulement juste attaché, non mesuré et aménagé. C'est la vue recyclée, pas la vue liée à l'élément de données actuel. Ce qui présente des problèmes comme la troncature de vue illustrée ci-dessus.


J'ai aussi essayé la hauteur de wrap_content sur la vue recycleur et invalidante du parent de recycleur jusqu'à ce que le recycleur et l'enfant sur parchemin venant SCROLL_STATE_IDLE. Ne fonctionne pas Je ne suis pas sûr de la façon dont un gestionnaire de disposition personnalisé peut aider ici.


Quelqu'un peut-il me guider dans la bonne direction?

+0

pouvez-vous ajouter votre fichier xml – Redman

+0

S'il vous plaît le trouver [ici] (https://gist.github.com/adroitandroid/85e7a66d7f796379649c2d9eab26cf76) –

+0

Le recyclerview en question est celui avec id "next_rv".En fait pour la solution détaillée ci-dessus, initialement je l'ai mis à hauteur match_parent et plus tard réinitialiser la hauteur à la 'maxHeight' obtenu –

Répondre

1

l'intérieur de votre adaptateur où je peux trouver deux cartes une sur le dessus et un autre sur le fond

Comment j'aurais défini ma mise en page est comme ceci:

Cardview1 

    LinearLayout1 --> orientation vertical 

    cardview2 (Top card where text is written) 

    Linearlayout2 (where I can see icons such as like etc)-->orientation horizontal 

fixer maintenant la hauteur de Linearlayout2 en fixant pour envelopper le contenu.

Et la hauteur de cardview2 doit être 0DP et ajouter du poids = 1

maintenant à l'intérieur cardview2 ajouter un TextView1 à matchparent en hauteur et en largeur.

mieux à l'intérieur textview1 ajouter ellipsize à la fin et ajouter des lignes max

Si vous voulez afficher toutes les lignes, essayez de trouver autoresizetextview bibliothèque, il peut être fondé ici ->AutoResizeTextView

Hope it helps.

+0

Merci d'avoir répondu. Ellipsize est une solution de contournement, il ne résout pas ma requête. Je connais l'autoresizetextview :) mais je ne cherche pas de taille de police variable sur ma liste. –

3

Je ne pouvais pas accepter la réponse @Pradeep Kumar Kushwaha parce que, par rapport à une solution, je ne veux pas de tailles de police différentes dans la liste. La cohérence est un élément clé dans la conception. La deuxième alternative qu'il a donnée ne pourrait pas fonctionner parce qu'avec ellipsize je devrais donner un bouton "plus" de quelque sorte pour l'utilisateur pour lire le contenu entier et mon affichage de texte prend déjà une action de clic. Mettre plus un autre endroit ne serait pas encore une bonne conception.

Modification de la conception avec la simple compromission du redimensionnement de la vue de recadrage lorsque l'élément tronqué le plus grand est mis au point, elle devient le cas d'utilisation simple de notifyItemChanged(). Même pour la tentative que j'ai faite en utilisant l'observateur attaché à la vue et l'écouteur d'état de défilement, notifyItemChanged pourrait être utilisé mais cette approche est juste trop hacky. C'est ce que je peux vivre avec le code et le design. Ici va le code requis.

@Override 
public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
    if (newState == RecyclerView.SCROLL_STATE_IDLE) { 
     int position = ((LinearLayoutManager) binding.nextRv.getLayoutManager()) 
       .findFirstVisibleItemPosition(); 
     if (position != nextSnippetAdapter.getItemCount() - 1) { 
      binding.nextRv.getAdapter().notifyItemRangeChanged(position, 2); 
     } else { 
      binding.nextRv.getAdapter().notifyItemChanged(position); 
     } 
    } 
} 

Pour ma configuration particulière, l'appel de ces deux éléments fonctionne. Il peut en outre être optimisé de manière à faire appel à un seul élément à position + 1 dans la plupart des cas, et à vérifier et appeler le cas approprié dans les cas (littéraux).

+0

Il s'agit d'un compromis de conception puisque les choses à l'écran devront se déplacer pour mettre au point l'ensemble de l'objet (en utilisant 'binding.contentScrollView.fullScroll (ScrollView.FOCUS_DOWN);') –

+0

En fait ce n'est pas un gros compromis de conception. Si je ne défile pas pour faire défiler la vue en bas, les choses vont bien. Il est perceptible que la vue a augmenté et débordé de l'écran, de sorte que l'on peut s'attendre à ce que l'utilisateur se défile pour voir le tout. –