J'ai également rencontré ce problème, mais dans mon cas, j'avais un FragmentPagerAdapter
qui fournissait le ViewPager
avec ses pages. Le problème que j'ai eu était que onMeasure()
le a ViewPager
été appelé avant la Fragments
création de l'un (et ne pouvait donc pas se dimensionner correctement).
Après un peu d'essais et d'erreurs, j'ai trouvé que la finishUpdate()
méthode de FragmentPagerAdapter est appelée après Fragments
avoir été initialisée (à partir instantiateItem()
de la FragmentPagerAdapter
) et également après / pendant le défilement de la page. J'ai fait une petite interface:
public interface AdapterFinishUpdateCallbacks
{
void onFinishUpdate();
}
que je passe dans mon FragmentPagerAdapter
et appelle:
@Override
public void finishUpdate(ViewGroup container)
{
super.finishUpdate(container);
if (this.listener != null)
{
this.listener.onFinishUpdate();
}
}
ce qui me permet à mon tour de faire appel setVariableHeight()
à ma CustomViewPager
mise en œuvre:
public void setVariableHeight()
{
// super.measure() calls finishUpdate() in adapter, so need this to stop infinite loop
if (!this.isSettingHeight)
{
this.isSettingHeight = true;
int maxChildHeight = 0;
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY);
for (int i = 0; i < getChildCount(); i++)
{
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED));
maxChildHeight = child.getMeasuredHeight() > maxChildHeight ? child.getMeasuredHeight() : maxChildHeight;
}
int height = maxChildHeight + getPaddingTop() + getPaddingBottom();
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.measure(widthMeasureSpec, heightMeasureSpec);
requestLayout();
this.isSettingHeight = false;
}
}
Je ne suis pas sûr que ce soit la meilleure approche, j'adorerais les commentaires si vous pensez que c'est bon / mauvais / mauvais, mais cela semble fonctionner assez bien dans ma mise en œuvre :)
J'espère que cela aide quelqu'un là-bas!
EDIT: J'ai oublié d'ajouter un requestLayout()
après l'appel super.measure()
(sinon il ne redessine pas la vue).
J'ai également oublié d'ajouter le rembourrage du parent à la hauteur finale.
J'ai également abandonné la conservation de la largeur / hauteur originale MeasureSpecs en faveur de la création d'une nouvelle au besoin. Avoir mis à jour le code en conséquence.
Un autre problème que j'avais était qu'il ne se dimensionnerait pas correctement dans un ScrollView
et a trouvé que le coupable mesurait l'enfant avec MeasureSpec.EXACTLY
au lieu de MeasureSpec.UNSPECIFIED
. Mis à jour pour refléter cela.
Ces modifications ont toutes été ajoutées au code. Vous pouvez consulter l'historique pour voir les anciennes versions (incorrectes) si vous le souhaitez.