web-dev-qa-db-fra.com

Comment définir la hauteur de recycleur sur l'article le plus élevé de RecyclerView?

Je dois m'assurer que la hauteur horizontale de recyclerview est la même que la hauteur du plus gros objet.

Les articles peuvent avoir une hauteur différente (élément = toujours la même image + le titre + le sous-titre, le titre et le sous-titre pourraient avoir une longueur infinie). Lorsque je définis Wrap_Content pour mon recyclageView, il redimensionnerait, en basant sur la hauteur des articles visibles qui rend le contenu ci-dessous Recyclerview sauter, et c'est quelque chose que je veux éviter.

Ce que je veux réaliser: what I want to achive La zone grise est visible de la fenêtre.

Donc, fondamentalement, je voudrais obtenir de la hauteur de la plus grande hauteur, puis mettez la hauteur de recyclerview à ce numéro.

Ce que j'ai déjà essayé, c'est une approximation élevée d'articles basés sur la longueur du titre + sous-titre, mais il est très inexact car, par exemple, même si deux titres ont la même longueur de texte qu'ils pouvaient avoir une largeur différente à cause de la police que j'utilise qui n'est pas une police monospace.

9
Jakub Mosakowski

Trop tard pour une réponse, mais peut-être que cela aidera quelqu'un.

J'ai eu du mal au même problème et je n'ai pas pu trouver une solution acceptable.

Résolu en suivant:

1) Tout d'abord, vous devez remplacer ONMEASURE à partir de la RecyclerView pour enregistrer la plus grande hauteur de l'élément:

class CustomRecycleView(ctx: Context, attrs: AttributeSet) : RecyclerView(ctx, attrs) {

    private var biggestHeight: Int = 0

    override fun onMeasure(widthSpec: Int, heightSpec: Int) {
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.measure(widthSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
            val h = child.measuredHeight
            if (h > biggestHeight) biggestHeight = h
        }

        super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(biggestHeight, MeasureSpec.EXACTLY))
    }

}

2) En You Layput, remplacez RecycletView avec ce CustomRecycleView:

<CustomRecycleView
   Android:layout_width="match_parent"
   Android:layout_height="wrap_content" />

onMeasure est appelé lorsqu'un nouvel élément de la liste est visible et si l'élément est le plus élevé, nous enregistrons cette valeur. Par exemple: Si le premier élément a la hauteur la plus basse, mais que les lates ont le plus haut, alors au début Recycletview sera une correspondance de la hauteur au premier élément, mais après le défilement, il restera correspondant au plus haut. Si vous n'avez pas besoin de faire une hauteur de recyclage de la hauteur de recyclage à l'article le plus élevé au démarrage, vous pouvez vous arrêter ici.

3) Pour ce faire au début, vous devez faire un hack (basé sur la suggestion de @Midaslefko): pour savoir initialement quelle sera la hauteur du plus haut élément, vous devez ajouter un mécanisme de défilement à la fin et au début. Je l'ai fait comme suit:

private fun initRecycleView(items: ArrayList<Object>) {
    val adapter = Adapter()
    rv.visibility = View.INVISIBLE
    rv.vadapter = adapter
    rv.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
    rv.setHasFixedSize(true)
    rv.smoothScrollToPosition(pinnedPosts.size)
    Handler().postDelayed({
        rv.smoothScrollToPosition(0)
    }, 300)
    Handler().postDelayed({
        rv.visibility = View.VISIBLE
    }, 700)
}

Définissez la visibilité de la vue recyclée sur Invisible et après 700 millisecondes visibles pour rendre ce processus invisible pour l'utilisateur. En outre, le défilement au démarrage est effectué avec un délai de 300 millisecondes, car sans retard, cela peut fonctionner de manière incorrecte. Dans mon cas, cela est nécessaire pour une liste de 3 éléments et ces retards sont optimaux pour moi.

N'oubliez pas non plus de supprimer tous les rappel du gestionnaire dans OnStop ()

0
Anonymous

vous devriez essayer avec un type_View différent

0
Govind Prajapati

Vous pouvez essayer ceci:

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            final int newHeight = recyclerView.getMeasuredHeight();
            if (0 != newHeight && minHeight < newHeight) {
            // keep track the height and prevent recycler view optimizing by resizing
                minHeight = newHeight;
                recyclerView.setMinimumHeight(minHeight);
            }
        }
    });
0
khanhuynh