104 votes

Comment puis-je faire quelque chose comme un FlowLayout dans Android?

Comment puis-je faire quelque chose comme un FlowLayout dans Android?

93voto

Romain Guy Points 57114

Si vous regardez le discours que j'ai prononcé à l'Devoxx de l'Université de la journée (disponible sur parleys.com), vous apprendrez comment faire vous-même. Au cours de la conversation que j'ai écrit un FlowLayout mise en œuvre sur scène pour montrer comment il est simple d'écrire des mises en page personnalisées.

La mise en œuvre est hébergé ici.

32voto

jfritz42 Points 2890

Il y a maintenant un open-source Android FlowLayout disponible sous licence BSD: https://github.com/ApmeM/android-flowlayout

24voto

Kevin Frugier Points 71

Je n'ai pas assez de réputation pour poster un commentaire de Romain Guy de réponse, mais c'est où cette réponse devrait être (j'ai créé un compte juste pour partager mon edit).

De toute façon, je vois d'autres personnes ont trouvé sa assez cool FlowLayout solution a des problèmes. J'ai pu trouver moi-même et j'ai vu, comme d'autres, que certains enfants ont été coupées. En regardant dans les détails à l'algorithme, il semble être un très simple erreur dans le calcul de la hauteur. Lorsque le dernier enfant est un être mis sur une nouvelle ligne, la hauteur n'a pas été correctement calculé. J'ai nettoyé un peu le calcul (il y avait un étrange usage de la "hauteur" par rapport à la currentHeight).

La modification suivante résout le problème du "dernier enfant est coupé si sur une nouvelle ligne":

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    int widthLimit = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);

    boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;

    int width = 0;

    int currentWidth = getPaddingLeft();
    int currentHeight = getPaddingTop();

    int maxChildHeight = 0;

    boolean breakLine = false;
    boolean newLine = false;
    int spacing = 0;

    final int count = getChildCount();
    for (int i = 0; i < count; i++)
    {
        View child = getChildAt(i);
        measureChild(child, widthMeasureSpec, heightMeasureSpec);

        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        spacing = mHorizontalSpacing;

        if (lp.horizontalSpacing >= 0)
        {
            spacing = lp.horizontalSpacing;
        }

        if (growHeight && (breakLine || ((currentWidth + child.getMeasuredWidth()) > widthLimit)))
        {               
            newLine = true;
            currentHeight += maxChildHeight + mVerticalSpacing;

            width = Math.max(width, currentWidth - spacing);

            currentWidth = getPaddingLeft();
            maxChildHeight = 0;
        }
        else
        {
            newLine = false;
        }

        maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());

        lp.x = currentWidth;
        lp.y = currentHeight;

        currentWidth += child.getMeasuredWidth() + spacing;

        breakLine = lp.breakLine;
    }

    if (newLine == false)
    {
        width = Math.max(width, currentWidth - spacing);
    }

    width += getPaddingRight();
    int height = currentHeight + maxChildHeight + getPaddingBottom();

    setMeasuredDimension(resolveSize(width, widthMeasureSpec),
            resolveSize(height, heightMeasureSpec));
}

2voto

Juozas Kontvainis Points 3294

Essayez de regarder les réponses à cette question, il y a quelques prometteur réponses de saut de Ligne disposition widget pour Android

0voto

gnB Points 760

Simple et agréable, autonome FlowLayout code ici (juste un peu concis gist.github fichiers):

http://hzqtc.github.io/2013/12/android-custom-layout-flowlayout.html

Cependant, l'activité de la boîte n'a pas de travail pour moi de me charger de la mise en page personnalisée.

J'ai trouvé ce travail autour [ en utilisant le 2-param .inflate() appel à partir de cet exemple ]:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    // ..

    setContentView(R.layout.main_res_layout_activity_main);

    ViewGroup flowContainer = getFlowLayoutView(); 

    // ..
}

ViewGroup getFlowLayoutView()
{
    LayoutInflater inflater = getLayoutInflater();

    ViewGroup flowLayout = 
        (ViewGroup)
            inflater.inflate(
                    R.layout.main_res_layout_activity_main,
                    (FlowLayout) findViewById(R.id.flow_container)
            );

    return flowLayout;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X