Android: Développer/réduire animation
Disons que j'ai une verticale linearLayout avec :
[v1]
[v2]
Par défaut v1 a visibily = DISPARU. Je voudrais montrer v1 avec une animation de développement et poussez vers le bas v2 en même temps.
J'ai essayé quelque chose comme ceci:
Animation a = new Animation()
{
int initialHeight;
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final int newHeight = (int)(initialHeight * interpolatedTime);
v.getLayoutParams().height = newHeight;
v.requestLayout();
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
initialHeight = height;
}
@Override
public boolean willChangeBounds() {
return true;
}
};
Mais avec cette solution, j'ai un clin d'oeil quand l'animation commence. Je pense que c'est causé par v1 affichage complet de la taille avant de l'animation est appliquée.
Avec javascript, c'est une ligne de jQuery! De toute manière simple de le faire avec android?
Vous devez vous connecter pour publier un commentaire.
Je vois que cette question est devenue populaire, donc je poste ma solution réelle. Le principal avantage est que vous n'avez pas à connaître l'étendue de la hauteur pour appliquer l'animation et une fois que la vue est développé, il s'adapte en hauteur si des modifications de contenu. Il fonctionne très bien pour moi.
Comme mentionné par @Jefferson dans les commentaires, vous pouvez obtenir une animation plus fluide par la modification de la durée (et donc la vitesse) de l'animation. Actuellement, il a été défini à une vitesse de 1dp/ms
a.setDuration(((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density)) * 4)
LayoutParams.UNSPECIFIED
lors de la mesure d'un point de Vue pas ajoutés à la mise en page.GONE
vue comme uneTextView
sont sûrs d'être mesuré à tort par le présent code, en raison de leur hauteur dépend de la largeur qu'ils peuvent prendre dans le parent. Im mon cas, j'ai joint monTextView
visibleLinearLayout
sans rembourrages/marges entre eux et a obtenuLienarLayout
's largeur, et l'a utilisé dansv.mesaure()
.expand()
doit définirv.getLayoutParams().height = 1;
autrement pré API21 versions d'android va annuler l'animation et la vue reste caché.v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
etv.getLayoutParams().height = interpolatedTime == 1 ? targetHeight : (int)(targetHeight * interpolatedTime);
Qui a fonctionné pour moi!v.getMeasuredHeight()
retourne 0, j'ai donc dû à la pré - mesure de la vue (j'. e.v.getHeight()
) et de modifier la visibilité à DISPARU dans lesonGlobalLayout()
de la vue et de passer la hauteur en tant que paramètre de laexpand(final View v)
méthode et ça fonctionne comme un charme!targetHeight
n'est probablement pas correspondre à la hauteur réelle de votre point de vue. Il pourrait être en raison d'un contenu dynamique. Difficile de le dire. Pour déboguer, il peut retirer les enfants des points de vue, un par un pour déterminer la cause de l'erreur de calcul.mDescription.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED))
view.getLayoutParams().height = interpolatedTime == 1 ? LayoutParams.WRAP_CONTENT : Math.max(1, (int)(targetHeight * interpolatedTime));
J'ai essayé de faire ce que je crois avoir été très proche de l'animation et a trouvé une solution élégante. Ce code suppose que vous allez toujours à partir de 0->h ou h->0 (h étant la hauteur maximale). Les trois paramètres du constructeur sont view = vue d'être animé (dans mon cas, une webview), targetHeight = la hauteur maximale de la vue, et bas = un booléen qui indique la direction (true = expansion, false = s'effondrent).
newHeight = (int) (viewHeight * (1 - interpolatedTime));
oùviewHeight
est la hauteur d'origine de la vue, définie dans le constructeur. Vous pouvez modifier votre code d'origine pour résoudre ce problème.Je suis tombé sur le même problème aujourd'hui et je pense que la vraie solution à cette question est ce
Vous devez définir cette propriété pour tous supérieur dispositions, qui sont impliqués dans le passage. Maintenant, si vous définissez la visibilité de la mise en page à DISPARU, l'autre prend l'espace, comme la disparition de l'un est de le relâcher. Il y aura une animation par défaut qui est une sorte de "fondu en fermeture", mais je pense que vous pouvez changer cela - mais le dernier je ne l'ai pas testé, pour l'instant.
J'ai pris @LenaYan 's solution qui ne fonctionnait pas correctement
pour moi (parce que c'était la transformation de la Vue en 0 de la hauteur de vue avant de s'effondrer et/ou à l'expansion de) et fait quelques changements.
Maintenant il fonctionne très bien, en prenant le point de Vue de l' précédente hauteur et de commencer à l'expansion de cette taille. L'effondrement est le même.
Vous suffit de copier et de coller le code ci-dessous:
Utilisation:
Assez facile!
Grâce LenaYan pour le code initial!
Une alternative est d'utiliser une échelle d'animation avec l'échelle suivante, les facteurs de croissance:
et pour la réduction:
@Tom Esterez de réponse, mais mis à jour pour utiliser la vue.measure() correctement par Android getMeasuredHeight renvoie des valeurs erronées !
Ok, je viens de trouver un TRÈS laid solution :
Hésitez pas à proposer une meilleure solution !
View.onMeause(widthMeasureSpec, heightMeasureSpec)
invokation, de sorte que la largeur et la hauteur de spécifications doit être échangé.Si vous ne voulez pas de développer ou de réduire tout le chemin - là est un simple HeightAnimation -
Utilisation:
J'ai adapté actuellement accepté de répondre par Tom Esterez, qui a travaillé, mais a eu un agitée et pas très fluide de l'animation. Ma solution fondamentalement remplace le
Animation
avec unValueAnimator
, qui peut être équipée avec unInterpolator
de votre choix pour obtenir divers effets tels que le dépassement, rebond, accélérer, etc.Cette solution fonctionne très bien avec des vues qui ont une dynamique à la hauteur (c'est à dire à l'aide de
WRAP_CONTENT
), comme première mesure la réelle hauteur requise et puis s'anime à la hauteur.Il vous suffit alors d'appeler
expand( myView );
oucollapse( myView );
.Je voudrais ajouter quelque chose à la très utile la réponse ci-dessus. Si vous ne connaissez pas la hauteur que vous aurez depuis votre point de vue .getHeight() renvoie 0, vous pouvez effectuer les opérations suivantes pour obtenir la hauteur:
Où DUMMY_HIGH_DIMENSIONS est la largeur/hauteur (en pixels) de votre point de vue est limité à ... avoir cette énorme nombre est raisonnable lorsque la vue est encapsulé avec un ScrollView.
Ceci est un extrait de code que j'ai utilisé pour redimensionner la largeur de vue (LinearLayout) avec animation.
Le code est censé faire d'élargir ou de rétrécir en fonction de la taille de la cible. Si vous voulez un fill_parent largeur, vous aurez à passer le parent .getMeasuredWidth comme cible de largeur, tandis que le paramétrage de l'indicateur de vrai.
Espère que cela aidera certains d'entre vous.
}
resizeAnim.start()
. Ont également essayé avec et sanssetFillAfter(true)
.startAnimation(resizeAnim)
sur la vue.Une animation plus fluide veuillez utiliser le Gestionnaire de la méthode run.....Et Profitez de Développer /réduire animation
}
Et Appel à l'aide de ce code:
Autre solution est:
L'ajout de Tom Esterez de excellente réponse et Erik B excellente mise à jour à elle, je pensais que je poste ma propre, le compactage de la dilater et de se contracter méthodes en une seule. De cette façon, vous pourriez, par exemple, ont une action comme ça...
... qui appelle la méthode ci-dessous et de le laisser décider quoi faire après chaque onClick()...
Oui, je suis d'accord avec les commentaires ci-dessus. Et en effet, il semble y avoir le droit (ou au moins le plus simple?) chose à faire est de spécifier (en XML), une mise en page initiale de la hauteur de "0px" -- et puis vous pouvez passer à un autre argument en faveur de "toHeight" (c'est à dire la "hauteur") pour le constructeur de votre Animation personnalisée sous-classe, par exemple dans l'exemple ci-dessus, il ressemblerait à quelque chose comme ceci:
De toute façon, espérons que ça aide! 🙂
Voici ma solution. Je pense que c'est plus simple. Il se développe seulement la vue, mais peut facilement être étendu.
Je pense que la solution la plus simple est de mettre
android:animateLayoutChanges="true"
à votreLinearLayout
et puis juste afficher/masquer la vue par paramétrer sa visibilité. Fonctionne comme un charme, mais vous n'avez aucun contrôle sur l'animation de la duréesolutions combinées de @Tom Esterez et @Geraldo Neto
Vous êtes sur la bonne voie. Assurez-vous que vous avez v1 avoir une mise en page à la hauteur de zéro à droite avant le début de l'animation. Vous souhaitez initialiser votre installation ressemble à la première image de l'animation avant de commencer l'animation.
C'était ma solution, à mon
ImageView
se développe à partir de100%
à200%
et revenir à sa taille d'origine, à l'aide de deux fichiers d'animation à l'intérieur deres/anim/
dossieranim_grow.xml
anim_shrink.xml
Envoyer un
ImageView
ma méthodesetAnimationGrowShrink()
setAnimationGrowShrink()
méthode:C'est une bonne solution de travail, je l'ai testé:
Exapnd:
Effondrement:
Valeur Animateur:
La vue v est la vue de l'être animé, PARENT_VIEW est le récipient contenant la vue.
Faisant usage de Kotlin Fonctions d'Extension c'est testé et plus courte réponse
Appelez simplement animateVisibility(agrandir/réduire) sur n'importe quelle Vue.
C'est vraiment simple avec droidQuery. Pour le départ, pensez à cette disposition:
Nous pouvons animer la hauteur de la valeur souhaitée à - dire
100dp
- en utilisant le code suivant:Ensuite utiliser
droidQuery
pour animer. La façon la plus simple est avec ceci:À rendre l'animation plus attrayants, envisager d'ajouter un assouplissement:
Vous pouvez également modifier la durée sur
AnimationOptions
à l'aide de laduration()
méthode, ou la poignée de ce qui se passe quand la fin de l'animation. Pour un exemple complexe, essayez:Meilleure solution pour agrandir ou réduire l'affichage de l':
onCheckedChanged
.Vous pouvez utiliser un ViewPropertyAnimator avec une légère torsion. À l'effondrement, à l'échelle de la vue à une hauteur de 1 pixel, puis le cacher. D'élargir, de le montrer, puis le développer à sa hauteur.
Le pivot raconte le point de vue où l'échelle de, défaut est dans le milieu. La durée est facultatif (défaut = 1000). Vous pouvez également définir l'interpolateur à utiliser, comme la
.setInterpolator(new AccelerateDecelerateInterpolator())
J'ai créé la version dans laquelle vous n'avez pas besoin de spécifier un modèle de hauteur, d'où il est beaucoup plus facile et plus propre à utiliser. La solution est de prendre de la hauteur dans la première image de l'animation (c'est à ce moment, au moins lors de mes tests). De cette façon, vous pouvez fournir une Vue d'un arbitraire de la hauteur et de la marge du bas.
Il y a aussi un petit hack dans le constructeur de la marge du bas est fixé à -10000 de sorte que le point de vue reste caché avant la transformation (évite le scintillement).
Utilisation ValueAnimator:
mainView.getLayoutParams().height = height
.La classe peut être appelée de la manière suivante
Basée sur des solutions par @Tom Esterez et @Seth Nelson (top 2) je simlified eux. Ainsi que des solutions originales il ne dépend pas d'options pour les Développeurs (les paramètres d'animation).
J'ai utilisé le même bloc de code qui ont utilisé accepté de répondre , Mais il l'habitude de travailler comme même dans android 9 , mise à jour de la mesure en fonction de ce
Comment la contrainte des œuvres peu différent dans android 9.