416 lines
13 KiB
Java
416 lines
13 KiB
Java
package com.example.boidelov3;
|
|
|
|
import android.animation.ArgbEvaluator;
|
|
import android.animation.ValueAnimator;
|
|
import android.content.Context;
|
|
import android.graphics.drawable.ColorDrawable;
|
|
import android.os.Build;
|
|
import android.os.VibrationEffect;
|
|
import android.os.Vibrator;
|
|
import android.view.View;
|
|
import android.view.animation.Animation;
|
|
import android.view.animation.AnimationUtils;
|
|
import android.view.animation.Interpolator;
|
|
import android.view.animation.OvershootInterpolator;
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
/**
|
|
* Classe utilitaire pour les animations et effets visuels
|
|
*/
|
|
public class BoideloAnimationUtils {
|
|
|
|
private static final Interpolator OVERSHOOT = new OvershootInterpolator();
|
|
|
|
/**
|
|
* Anime le changement de couleur de fond d'une vue
|
|
*
|
|
* @param view La vue à animer
|
|
* @param targetColor La couleur cible
|
|
* @param duration La durée de l'animation en ms
|
|
*/
|
|
public static void animateBackgroundColor(View view, int targetColor, int duration) {
|
|
if (view == null) return;
|
|
|
|
int currentColor = getBackgroundColor(view);
|
|
if (currentColor == targetColor) return;
|
|
|
|
ValueAnimator anim = ValueAnimator.ofObject(new ArgbEvaluator(), currentColor, targetColor);
|
|
anim.setDuration(duration);
|
|
anim.addUpdateListener(animation -> {
|
|
int color = (int) animation.getAnimatedValue();
|
|
view.setBackgroundColor(color);
|
|
});
|
|
anim.start();
|
|
}
|
|
|
|
/**
|
|
* Anime le changement de couleur de fond avec la durée par défaut (500ms)
|
|
*/
|
|
public static void animateBackgroundColor(View view, int targetColor) {
|
|
animateBackgroundColor(view, targetColor, 500);
|
|
}
|
|
|
|
/**
|
|
* Obtient la couleur de fond actuelle d'une vue
|
|
*/
|
|
private static int getBackgroundColor(View view) {
|
|
if (view.getBackground() instanceof ColorDrawable) {
|
|
return ((ColorDrawable) view.getBackground()).getColor();
|
|
}
|
|
return 0xFFFFFFFF; // Blanc par défaut
|
|
}
|
|
|
|
/**
|
|
* Déclenche une vibration haptique
|
|
*
|
|
* @param context Le contexte
|
|
* @param duration Durée de la vibration en ms
|
|
*/
|
|
public static void triggerHapticFeedback(Context context, int duration) {
|
|
if (context == null) return;
|
|
|
|
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
|
if (vibrator != null && vibrator.hasVibrator()) {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
VibrationEffect effect = VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
|
|
vibrator.vibrate(effect);
|
|
} else {
|
|
vibrator.vibrate(duration);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Déclenche une vibration haptique courte (100ms)
|
|
*/
|
|
public static void triggerHapticFeedback(Context context) {
|
|
triggerHapticFeedback(context, 100);
|
|
}
|
|
|
|
/**
|
|
* Déclenche une vibration haptique de succès
|
|
*/
|
|
public static void triggerSuccessHaptic(Context context) {
|
|
if (context == null) return;
|
|
|
|
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
|
if (vibrator != null && vibrator.hasVibrator() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
long[] pattern = {0, 50, 50, 50};
|
|
VibrationEffect effect = VibrationEffect.createWaveform(pattern, -1);
|
|
vibrator.vibrate(effect);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Déclenche une vibration haptique d'erreur
|
|
*/
|
|
public static void triggerErrorHaptic(Context context) {
|
|
if (context == null) return;
|
|
|
|
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
|
if (vibrator != null && vibrator.hasVibrator() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
long[] pattern = {0, 100, 50, 100};
|
|
VibrationEffect effect = VibrationEffect.createWaveform(pattern, -1);
|
|
vibrator.vibrate(effect);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Anime l'apparition d'une vue avec un effet de fade-in
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void fadeIn(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.setAlpha(0f);
|
|
view.setVisibility(View.VISIBLE);
|
|
view.animate()
|
|
.alpha(1f)
|
|
.setDuration(duration)
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime la disparition d'une vue avec un effet de fade-out
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void fadeOut(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.alpha(0f)
|
|
.setDuration(duration)
|
|
.withEndAction(() -> view.setVisibility(View.GONE))
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de scale
|
|
*
|
|
* @param view La vue à animer
|
|
* @param scale Échelle cible (1.0 = normal, 0.5 = moitié)
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void scale(View view, float scale, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.scaleX(scale)
|
|
.scaleY(scale)
|
|
.setDuration(duration)
|
|
.setInterpolator(OVERSHOOT)
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de slide depuis le bas
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void slideUp(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.setTranslationY(view.getHeight());
|
|
view.setVisibility(View.VISIBLE);
|
|
view.animate()
|
|
.translationY(0f)
|
|
.setDuration(duration)
|
|
.setInterpolator(new android.view.animation.DecelerateInterpolator())
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Applique une animation de pression à un bouton
|
|
*
|
|
* @param view La vue (bouton) à animer
|
|
*/
|
|
public static void applyButtonPressAnimation(View view) {
|
|
if (view == null) return;
|
|
|
|
view.setOnTouchListener((v, event) -> {
|
|
switch (event.getAction()) {
|
|
case android.view.MotionEvent.ACTION_DOWN:
|
|
v.animate()
|
|
.scaleX(0.95f)
|
|
.scaleY(0.95f)
|
|
.setDuration(100)
|
|
.start();
|
|
return true;
|
|
case android.view.MotionEvent.ACTION_UP:
|
|
case android.view.MotionEvent.ACTION_CANCEL:
|
|
v.animate()
|
|
.scaleX(1f)
|
|
.scaleY(1f)
|
|
.setDuration(100)
|
|
.start();
|
|
v.performClick();
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de pulsation
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée d'un cycle de pulsation
|
|
*/
|
|
public static void pulse(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.scaleX(1.05f)
|
|
.scaleY(1.05f)
|
|
.setDuration(duration / 2)
|
|
.withEndAction(() -> {
|
|
view.animate()
|
|
.scaleX(1f)
|
|
.scaleY(1f)
|
|
.setDuration(duration / 2)
|
|
.start();
|
|
})
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de shake (tremblement)
|
|
*
|
|
* @param view La vue à animer
|
|
*/
|
|
public static void shake(View view) {
|
|
if (view == null) return;
|
|
|
|
Animation shake = AnimationUtils.loadAnimation(view.getContext(), R.anim.button_press);
|
|
view.startAnimation(shake);
|
|
}
|
|
|
|
/**
|
|
* Obtient la couleur depuis une ressource de couleur
|
|
*/
|
|
public static int getColorFromResource(Context context, int colorResId) {
|
|
return ContextCompat.getColor(context, colorResId);
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de bounce (rebond)
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void bounce(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.scaleY(0.8f)
|
|
.scaleX(0.8f)
|
|
.setDuration(duration / 2)
|
|
.setInterpolator(new android.view.animation.DecelerateInterpolator())
|
|
.withEndAction(() -> {
|
|
view.animate()
|
|
.scaleY(1f)
|
|
.scaleX(1f)
|
|
.setDuration(duration / 2)
|
|
.setInterpolator(OVERSHOOT)
|
|
.start();
|
|
})
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue pour la supprimer (slide out + fade out)
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
* @param endAction Action à exécuter après l'animation
|
|
*/
|
|
public static void slideOutToRemove(View view, int duration, Runnable endAction) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.translationX(-view.getWidth())
|
|
.alpha(0f)
|
|
.setDuration(duration)
|
|
.setInterpolator(new android.view.animation.AccelerateInterpolator())
|
|
.withEndAction(endAction)
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime l'apparition d'une vue (slide in + fade in)
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void slideIn(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.setTranslationX(view.getWidth());
|
|
view.setAlpha(0f);
|
|
view.setVisibility(View.VISIBLE);
|
|
view.animate()
|
|
.translationX(0f)
|
|
.alpha(1f)
|
|
.setDuration(duration)
|
|
.setInterpolator(new android.view.animation.DecelerateInterpolator())
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de rotation
|
|
*
|
|
* @param view La vue à animer
|
|
* @param degrees Angle de rotation en degrés
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void rotate(View view, float degrees, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.rotation(degrees)
|
|
.setDuration(duration)
|
|
.setInterpolator(new android.view.animation.DecelerateInterpolator())
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de wiggle (gauche-droite)
|
|
*
|
|
* @param view La vue à animer
|
|
*/
|
|
public static void wiggle(View view) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.rotation(5f)
|
|
.setDuration(50)
|
|
.withEndAction(() -> {
|
|
view.animate()
|
|
.rotation(-5f)
|
|
.setDuration(50)
|
|
.withEndAction(() -> {
|
|
view.animate()
|
|
.rotation(3f)
|
|
.setDuration(50)
|
|
.withEndAction(() -> {
|
|
view.animate()
|
|
.rotation(0f)
|
|
.setDuration(50)
|
|
.start();
|
|
})
|
|
.start();
|
|
})
|
|
.start();
|
|
})
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de pop-in (apparition avec scale)
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
*/
|
|
public static void popIn(View view, int duration) {
|
|
if (view == null) return;
|
|
|
|
view.setScaleX(0f);
|
|
view.setScaleY(0f);
|
|
view.setAlpha(0f);
|
|
view.setVisibility(View.VISIBLE);
|
|
view.animate()
|
|
.scaleX(1f)
|
|
.scaleY(1f)
|
|
.alpha(1f)
|
|
.setDuration(duration)
|
|
.setInterpolator(OVERSHOOT)
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* Anime une vue avec un effet de pop-out (disparition avec scale)
|
|
*
|
|
* @param view La vue à animer
|
|
* @param duration Durée de l'animation
|
|
* @param endAction Action à exécuter après l'animation
|
|
*/
|
|
public static void popOut(View view, int duration, Runnable endAction) {
|
|
if (view == null) return;
|
|
|
|
view.animate()
|
|
.scaleX(0f)
|
|
.scaleY(0f)
|
|
.alpha(0f)
|
|
.setDuration(duration)
|
|
.setInterpolator(new android.view.animation.AccelerateInterpolator())
|
|
.withEndAction(endAction)
|
|
.start();
|
|
}
|
|
}
|