Comment puis-je faire quelque chose comme un FlowLayout
dans Android?
Réponses
Trop de publicités?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.
Il y a maintenant un open-source Android FlowLayout disponible sous licence BSD: https://github.com/ApmeM/android-flowlayout
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));
}
Essayez de regarder les réponses à cette question, il y a quelques prometteur réponses de saut de Ligne disposition widget pour Android
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;
}