package com.example.lovedemo.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.KeyEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.example.lovedemo.R;
import com.example.lovedemo.dialog.CloseAlertDialogUtils;
import com.example.lovedemo.dialog.QuitDialog;
import com.example.lovedemo.dialog.VindicateDialog;
import com.example.lovedemo.tools.Utils;
import com.example.lovedemo.view.StarRainView;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private FrameLayout container;
// 多种星形资源
private int[] starResIds = {
R.drawable.a1, R.drawable.a2, R.drawable.a3,
R.drawable.a4, R.drawable.a5, R.drawable.a6,
R.drawable.a7, R.drawable.a8, R.drawable.a9,
R.drawable.a10, R.drawable.a11, R.drawable.a12,
R.drawable.a13, R.drawable.a14, R.drawable.a15,
R.drawable.a16, R.drawable.a17, R.drawable.a18, R.drawable.a19
};
private int[] starResId = {
R.drawable.xin1, R.drawable.xin2, R.drawable.xin3,
R.drawable.xin4, R.drawable.xxing
};
private Random random = new Random();
private long currentDelay = 0;
private final long delayBetweenStars = 500; // 每颗星星间隔时间
private Handler starHandler = new Handler(Looper.getMainLooper());
private Runnable starRunnable;
private boolean isStarAnimationRunning = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
container = findViewById(R.id.container);
// 依次绘制图形
drawLetterI();
drawHeart();
drawLetterU();
startRandomStarAnimation();
}
// 创建带有动画的 ImageView
private ImageView createStar(float x, float y) {
ImageView imageView = new ImageView(this);
imageView.setImageResource(starResIds[random.nextInt(starResIds.length)]);
imageView.setLayoutParams(new FrameLayout.LayoutParams(35, 35));
imageView.setX(x);
imageView.setY(y);
imageView.setAlpha(0f);
imageView.setScaleX(0.5f);
imageView.setScaleY(0.5f);
// 缩放和透明度动画
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(imageView, "scaleX", 0.5f, 1f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(imageView, "scaleY", 0.5f, 1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(alphaAnim, scaleXAnim, scaleYAnim);
animatorSet.setDuration(3500);
// 延迟执行
new Handler(Looper.getMainLooper()).postDelayed(animatorSet::start, currentDelay);
currentDelay += delayBetweenStars;
return imageView;
}
// 绘制字母 I
private void drawLetterI() {
int centerX = 530;
int startY = 200;
// 绘制顶部横杠
for (int i = -2; i < 3; i++) {
ImageView topBarStar = createStar(centerX + i * 40, startY - 40);
container.addView(topBarStar);
}
// 绘制垂直列(中间部分)
for (int i = 0; i < 9; i++) {
float y = startY + i * 40;
ImageView star = createStar(centerX, y);
container.addView(star);
}
// 绘制底部横杠
for (int i = -2; i < 3; i++) {
ImageView bottomBarStar = createStar(centerX + i * 40, startY + 8 * 40);
container.addView(bottomBarStar);
}
}
// 绘制心形图案
private void drawHeart() {
int centerX = 530;
int centerY = 900;
int size = 15;
// 设置图片资源,例如你有一个叫 "heart_image" 的图片资源
for (double t = 0; t < 2 * Math.PI; t += 0.2) {
double xVal = 16 * Math.pow(Math.sin(t), 3);
double yVal = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
float px = (float) (centerX + xVal * size);
float py = (float) (centerY - yVal * size);
ImageView star = createStar(px, py);
container.addView(star);
}
// 添加心形中央图片并设置缩放动画
new Handler(Looper.getMainLooper()).postDelayed(() -> {
ImageView heartImage = new ImageView(this);
heartImage.setImageResource(R.drawable.h_m_m); // 使用自己的心形图片资源
heartImage.setLayoutParams(new FrameLayout.LayoutParams(260, 260)); // 设置合适的大小
heartImage.setX(centerX - 105); // 设置图片X位置
heartImage.setY(centerY - 65); // 设置图片Y位置
// 设置缩放动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(heartImage, "scaleX", 0f, 1f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(heartImage, "scaleY", 0f, 1f);
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(heartImage, "alpha", 0f, 1f);
AnimatorSet heartAnimatorSet = new AnimatorSet();
heartAnimatorSet.playTogether(scaleXAnim, scaleYAnim, alphaAnim);
heartAnimatorSet.setDuration(3500); // 设置动画时长
container.addView(heartImage);
heartAnimatorSet.start();
}, 20 * 1000); // 设置延迟,在绘制完心形图案后开始执行
}
// 绘制字母 U(底部为圆弧)
private void drawLetterU() {
long totalDuration = 0;
int startX = 410;
int startY = 1300;
// 左侧横线
for (int i = -6; i < 8; i++) {
float x = (float) (startX + i * -5);
ImageView star = createStar(x, startY);
container.addView(star);
}
// 右侧横线
for (int i = -6; i < 8; i++) {
float x = startX + i * -5;
ImageView star = createStar(x + 250, startY);
container.addView(star);
}
// 左侧竖线
for (int i = 0; i < 8; i++) {
float y = startY + i * 40;
ImageView star = createStar(startX, y);
container.addView(star);
}
// 右侧竖线(更宽了)
for (int i = 0; i < 8; i++) {
float y = startY + i * 40;
ImageView star = createStar(startX + 250, y);
container.addView(star);
}
// 底部绘制一个圆弧形(近似)
int centerX = startX + 125; // 新增宽度后的新中点
int centerY = startY + 7 * 40; // Y 不变
int radius = 110; // 增大半径以适应新宽度
int points = 9; // 更多点数,圆弧更平滑
for (int i = 0; i < points; i++) {
double angle = Math.PI * i / (points - 1); // 从 π 到 2π 的角度(下半圆)
float x = (float) (centerX + radius * Math.cos(angle));
float y = (float) (centerY + radius * Math.sin(angle));
ImageView star = createStar(x, y);
container.addView(star);
totalDuration += 5500;
}
new Handler(Looper.getMainLooper()).postDelayed(this::triggerCornerAnimations, totalDuration);
}
private void triggerCornerAnimations() {
// 右上:从左向右移动
showCornerImageWithTranslation(R.drawable.up_right, container.getWidth(), 0, container.getWidth() - 150, -35);
// 中间:从左到中间移动
showCornerImageWithTranslation(R.drawable.upmidd, -150, 100, container.getWidth() / 2 - 130, -35, 250, 150);
// 左上:从左移动到左上
showCornerImageWithTranslation(R.drawable.up_left, -100, 0, 0, -35);
// 左下角动画:保持缩放效果
animateCorner(R.drawable.down_left, -10, container.getHeight() - 150);
//下边距动画:保持缩放效果
Utils.animateCorner(R.drawable.downmidd, container.getWidth() / 2 - 120, container.getHeight() - 125, MainActivity.this, container, 250, 200);
// 右下角动画:保持缩放效果
animateCorner(R.drawable.down_right, container.getWidth() - 140, container.getHeight() - 150);
// 延迟执行,在所有动画完成后添加心形图案下方的图片
new Handler(Looper.getMainLooper()).postDelayed(this::addImagesNearHeart, 6500); // 调整延迟时间确保所有动画完成
}
private void animateCorner(int resId, float startX, float startY) {
ImageView cornerImage = new ImageView(this);
cornerImage.setImageResource(resId);
cornerImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150));
cornerImage.setX(startX);
cornerImage.setY(startY);
cornerImage.setAlpha(0f);
AnimatorSet animatorSet = new AnimatorSet();
// 缩放动画:保持原有逻辑
cornerImage.setScaleX(0.5f);
cornerImage.setScaleY(0.5f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(cornerImage, "scaleX", 0.5f, 1f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(cornerImage, "scaleY", 0.5f, 1f);
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(cornerImage, "alpha", 0f, 1f);
animatorSet.playTogether(scaleXAnim, scaleYAnim, alphaAnim);
animatorSet.setDuration(3500);
container.addView(cornerImage);
animatorSet.start();
}
private void showCornerImageWithTranslation(int resId, float startX, float startY, float endX, float endY) {
ImageView cornerImage = new ImageView(this);
cornerImage.setImageResource(resId);
cornerImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150));
cornerImage.setX(startX);
cornerImage.setY(startY);
cornerImage.setAlpha(0f);
cornerImage.setScaleX(1f);
cornerImage.setScaleY(1f);
container.addView(cornerImage);
// Alpha animation
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(cornerImage, "alpha", 0f, 1f);
// Translation animations
ObjectAnimator translateXAnim = ObjectAnimator.ofFloat(cornerImage, "x", startX, endX);
ObjectAnimator translateYAnim = ObjectAnimator.ofFloat(cornerImage, "y", startY, endY);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(alphaAnim, translateXAnim, translateYAnim);
animatorSet.setDuration(3500);
animatorSet.start();
}
// 创建平移动画的辅助方法
private void showCornerImageWithTranslation(int resId, float startX, float startY, float endX, float endY, int width, int height) {
ImageView cornerImage = new ImageView(this);
cornerImage.setImageResource(resId);
// 设置图片的宽度和高度
cornerImage.setLayoutParams(new FrameLayout.LayoutParams(width, height));
cornerImage.setX(startX);
cornerImage.setY(startY);
cornerImage.setAlpha(0f);
cornerImage.setScaleX(1f);
cornerImage.setScaleY(1f);
container.addView(cornerImage);
// Alpha 动画
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(cornerImage, "alpha", 0f, 1f);
ObjectAnimator translateXAnim = ObjectAnimator.ofFloat(cornerImage, "x", startX, endX);
ObjectAnimator translateYAnim = ObjectAnimator.ofFloat(cornerImage, "y", startY, endY);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(alphaAnim, translateXAnim, translateYAnim);
animatorSet.setDuration(3500);
// 在动画结束后,添加缩放动画的新图片
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// 在图片的正中心创建新图片
float centerX = (float) (cornerImage.getX() + (cornerImage.getWidth() / 1.6));
float centerY = (float) (cornerImage.getY() + (cornerImage.getHeight() / 1.9));
// 创建新图片
ImageView zoomImage = new ImageView(MainActivity.this);
zoomImage.setImageResource(R.drawable.love_middle_down); // 替换成你的新图片资源
zoomImage.setLayoutParams(new FrameLayout.LayoutParams(50, 50)); // 设置缩放图片的大小
container.addView(zoomImage);
// 设置新图片的初始位置为正中心
zoomImage.setX(centerX - 50); // 100/2 使得图片位于中心
zoomImage.setY(centerY - 50); // 100/2 使得图片位于中心
// 创建缩放动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(zoomImage, "scaleX", 0f, 1f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(zoomImage, "scaleY", 0f, 1f);
AnimatorSet scaleAnimatorSet = new AnimatorSet();
scaleAnimatorSet.playTogether(scaleXAnim, scaleYAnim);
scaleAnimatorSet.setDuration(3500); // 设定缩放动画的时长
scaleAnimatorSet.start();
// 在屏幕的左右两边添加缩放动画的新图片
// 左侧图片
ImageView leftImage = new ImageView(MainActivity.this);
leftImage.setImageResource(R.drawable.midd_midd_left); // 替换成你左侧的图片资源
leftImage.setLayoutParams(new FrameLayout.LayoutParams(150, ViewGroup.LayoutParams.MATCH_PARENT)); // 设置左侧图片的大小
container.addView(leftImage);
// 设置左侧图片的位置
leftImage.setX(0); // 屏幕左边
leftImage.setY(centerY - 50); // 垂直居中
// 创建左侧图片的缩放动画
ObjectAnimator leftScaleXAnim = ObjectAnimator.ofFloat(leftImage, "scaleX", 0f, 1f);
ObjectAnimator leftScaleYAnim = ObjectAnimator.ofFloat(leftImage, "scaleY", 0f, 1f);
AnimatorSet leftScaleAnimatorSet = new AnimatorSet();
leftScaleAnimatorSet.playTogether(leftScaleXAnim, leftScaleYAnim);
leftScaleAnimatorSet.setDuration(3500);
leftScaleAnimatorSet.start();
// 右侧图片
ImageView rightImage = new ImageView(MainActivity.this);
rightImage.setImageResource(R.drawable.midd_midd_right); // 替换成你右侧的图片资源
rightImage.setLayoutParams(new FrameLayout.LayoutParams(150, ViewGroup.LayoutParams.MATCH_PARENT)); // 设置右侧图片的大小
container.addView(rightImage);
// 设置右侧图片的位置
rightImage.setX(getResources().getDisplayMetrics().widthPixels - 150); // 屏幕右边
rightImage.setY(centerY - 50); // 垂直居中
// 创建右侧图片的缩放动画
ObjectAnimator rightScaleXAnim = ObjectAnimator.ofFloat(rightImage, "scaleX", 0f, 1f);
ObjectAnimator rightScaleYAnim = ObjectAnimator.ofFloat(rightImage, "scaleY", 0f, 1f);
AnimatorSet rightScaleAnimatorSet = new AnimatorSet();
rightScaleAnimatorSet.playTogether(rightScaleXAnim, rightScaleYAnim);
rightScaleAnimatorSet.setDuration(3500);
rightScaleAnimatorSet.start();
}
});
animatorSet.start();
}
private void addImagesNearHeart() {
// 获取心形图案的位置
int centerX = 530;
int centerY = 900;
// 左侧图片
ImageView leftImage = new ImageView(this);
leftImage.setImageResource(R.drawable.love_m_left); // 替换成你的左侧图片资源
leftImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150)); // 设置图片大小
leftImage.setX(centerX - 250); // 设置位置,心形图片左侧
leftImage.setY(centerY + 100); // 设置位置,心形图片下方
leftImage.setAlpha(0f); // 初始透明度为0
container.addView(leftImage);
// 右侧图片
ImageView rightImage = new ImageView(this);
rightImage.setImageResource(R.drawable.hudei); // 替换成你的右侧图片资源
rightImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150)); // 设置图片大小
rightImage.setX(centerX + 280); // 设置位置,心形图片右侧
rightImage.setY(centerY + 50); // 设置位置,心形图片下方
rightImage.setAlpha(0f); // 初始透明度为0
container.addView(rightImage);
// 缩放动画
ObjectAnimator scaleXLeft = ObjectAnimator.ofFloat(leftImage, "scaleX", 0f, 1f);
ObjectAnimator scaleYLeft = ObjectAnimator.ofFloat(leftImage, "scaleY", 0f, 1f);
ObjectAnimator alphaLeft = ObjectAnimator.ofFloat(leftImage, "alpha", 0f, 1f);
ObjectAnimator scaleXRight = ObjectAnimator.ofFloat(rightImage, "scaleX", 0f, 1f);
ObjectAnimator scaleYRight = ObjectAnimator.ofFloat(rightImage, "scaleY", 0f, 1f);
ObjectAnimator alphaRight = ObjectAnimator.ofFloat(rightImage, "alpha", 0f, 1f);
// 创建 AnimatorSet
AnimatorSet animatorSetLeft = new AnimatorSet();
animatorSetLeft.playTogether(scaleXLeft, scaleYLeft, alphaLeft);
animatorSetLeft.setDuration(3500); // 设置动画时长
AnimatorSet animatorSetRight = new AnimatorSet();
animatorSetRight.playTogether(scaleXRight, scaleYRight, alphaRight);
animatorSetRight.setDuration(3500); // 设置动画时长
animatorSetRight.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
int type = 2;
VindicateDialog dialog = VindicateDialog.getInstance();
VindicateDialog.showConfirmDialog(MainActivity.this, "", "还没结束哦,请点击同意进入下一个页面哦= ̄ω ̄=",type);
dialog.setMonDialogButtonClickListener(new VindicateDialog.OnDialogButtonClickListener() {
@Override
public void onPositiveButtonClick(AlertDialog dialog) {
Intent intent = new Intent(MainActivity.this, VindicateActivity.class);
startActivity(intent);
finish(); //关闭当前Activity
}
@Override
public void onNegativeButtonClick(AlertDialog dialog) {
//点击不同意按钮关闭应用
dialog.dismiss();
CloseAlertDialogUtils instance = CloseAlertDialogUtils.getInstance();
CloseAlertDialogUtils.showConfirmDialog(MainActivity.this, "", "小姐姐确定要这么狠心的离开吗?还有惊喜哦,拜托看完好吗~(>﹏<)");
instance.setMonDialogButtonClickListener(new CloseAlertDialogUtils.OnDialogButtonClickListener() {
@Override
public void onClosePositiveButtonClick(AlertDialog dialog) {
Intent intent = new Intent(MainActivity.this, VindicateActivity.class);
startActivity(intent);
finish(); //关闭当前Activity
}
@Override
public void onCloseNegativeButtonClick(AlertDialog dialog) {
int type = 2;
//点击不同意按钮关闭应用
dialog.dismiss();
QuitDialog instance = QuitDialog.getInstance();
QuitDialog.showConfirmDialog(MainActivity.this, "", "即使不知归期,我也会默默等待,挥手道别,是为了更好的相遇。这次是真的要再见了小姐姐o(*≧▽≦)ツ",type);
instance.setMonDialogButtonClickListener(new QuitDialog.OnDialogButtonClickListener() {
@Override
public void onClosePositiveButtonClick(AlertDialog dialog) {
}
@Override
public void onCloseNegativeButtonClick(AlertDialog dialog) {
dialog.dismiss();
System.exit(0);
}
});
}
});
}
});
}
}, 10000); // 动画结束后延迟10秒
}
});
// 启动动画
animatorSetLeft.start();
animatorSetRight.start();
}
private void startRandomStarAnimation() {
isStarAnimationRunning = true;
starRunnable = new Runnable() {
@Override
public void run() {
if (!isStarAnimationRunning) return;
// 随机选择资源
int resId = starResId[random.nextInt(starResId.length)];
// 随机位置
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int screenHeight = getResources().getDisplayMetrics().heightPixels;
float x = random.nextInt(screenWidth - 100); // 留出边距
float y = random.nextInt(screenHeight - 100);
ImageView star = new ImageView(MainActivity.this);
star.setImageResource(resId);
star.setLayoutParams(new FrameLayout.LayoutParams(100, 100));
star.setX(x);
star.setY(y);
star.setAlpha(0f);
star.setScaleX(0.5f);
star.setScaleY(0.5f);
// 添加到容器中
container.addView(star);
// 动画
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(star, "alpha", 0f, 1f, 0f);
ObjectAnimator scaleUpX = ObjectAnimator.ofFloat(star, "scaleX", 0.5f, 1.2f);
ObjectAnimator scaleUpY = ObjectAnimator.ofFloat(star, "scaleY", 0.5f, 1.2f);
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(star, "scaleX", 1.2f, 0.5f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(star, "scaleY", 1.2f, 0.5f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(
ObjectAnimator.ofFloat(star, "alpha", 0f, 1f),
scaleUpX, scaleUpY,
scaleDownX, scaleDownY,
ObjectAnimator.ofFloat(star, "alpha", 1f, 0f)
);
animatorSet.setDuration(3500);
// 动画结束后移除视图
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
container.removeView(star);
}
});
animatorSet.start();
// 下一次随机延迟执行
long nextDelay = random.nextInt(1000) + 500; // 0.5s ~ 1.5s
starHandler.postDelayed(this, nextDelay);
}
};
starHandler.post(starRunnable);
}
//监听退出
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Utils.exit(MainActivity.this);
return false;
}
return super.onKeyDown(keyCode, event);
}
//停止星星动画
private void stopRandomStarAnimation() {
isStarAnimationRunning = false;
starHandler.removeCallbacks(starRunnable);
}
@Override
protected void onDestroy() {
stopRandomStarAnimation();
super.onDestroy();
}
}
package com.example.lovedemo.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.lovedemo.R;
import com.example.lovedemo.view.StarConcentricKnotView;
import java.util.concurrent.atomic.AtomicInteger;
public class VindicateActivity extends AppCompatActivity {
private FrameLayout container;
private int[] heartResId = {
R.drawable.right1, R.drawable.right2
};
private int[] heartResIds = {
R.drawable.up0, R.drawable.up1
};
private int currentHeartIndex = 0; // 当前心形索引
private long delayBetweenHearts = 100; // 每个心形之间的延迟时间
private long currentDelay = 0;
private long baseDelay = 0; // 全局基础延迟时间
private final long animationGroupInterval = 3500; // 每组动画之间间隔 1.5 秒
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vindicate);
container = findViewById(R.id.container);
// ✨ 添加 ConcentricKnotView 到容器中
StarConcentricKnotView knotView = new StarConcentricKnotView(this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
container.addView(knotView, params);
// ✨ 使用 ViewTreeObserver 确保 View 已完成布局后再启动动画
knotView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
knotView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
drawTopBorder(); // 主边框
drawTopBorderDots(); // 点缀边框
drawLeftBorder();
drawRightBorder();
drawBottomBorder();
drawBottomBorderDots(); // 点缀边框 - 下
}
// 创建带动画的心形 ImageView
private ImageView createHeart(float x, float y, boolean isSmall, long initialDelay) {
ImageView heart = new ImageView(this);
if (isSmall) {
heart.setImageResource(heartResId[currentHeartIndex]);
currentHeartIndex = (currentHeartIndex + 1) % heartResId.length;
heart.setLayoutParams(new FrameLayout.LayoutParams(50, 50));
heart.setAlpha(0f);
heart.setScaleX(0.5f);
heart.setScaleY(0.5f);
} else {
heart.setImageResource(heartResIds[currentHeartIndex]);
currentHeartIndex = (currentHeartIndex + 1) % heartResIds.length;
heart.setLayoutParams(new FrameLayout.LayoutParams(60, 60));
heart.setAlpha(0.5f);
heart.setScaleX(0.3f);
heart.setScaleY(0.3f);
}
heart.setX(x);
heart.setY(y);
ObjectAnimator alpha = ObjectAnimator.ofFloat(heart, "alpha", 0f, 1f);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(heart, "scaleX", 0f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(heart, "scaleY", 0f, 1f);
AnimatorSet set = new AnimatorSet();
set.playTogether(alpha, scaleX, scaleY);
set.setDuration(isSmall ? 2500 : 2800);
new Handler(Looper.getMainLooper()).postDelayed(set::start, initialDelay + currentDelay);
currentDelay += delayBetweenHearts;
return heart;
}
// 绘制上边框
private void drawTopBorder() {
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int spacing = 40; // 心形间距
int offset = (int) convertDpToPx(15); // 错落偏移量
for (int i = 0; i < screenWidth / spacing + 1; i++) {
float waveOffset = (float) Math.sin(i * Math.PI / 4) * offset;
float x = i * spacing;
float y = 0;
// 奇数索引项加上偏移
if (i % 2 == 1) {
y += waveOffset;
}
container.addView(createHeart(x, y,true,baseDelay));
}
baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay
}
private void drawTopBorderDots() {
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int spacing = 60; // 更稀疏一些
int offset = (int) convertDpToPx(10); // 小波浪偏移量
int baseY = 20; // 轻微偏移,让点缀图和主图有层次感
for (int i = 0; i < screenWidth / spacing + 1; i++) {
float waveOffset = (float) Math.sin(i * Math.PI / 4) * offset;
float x = i * spacing;
float y = baseY + waveOffset;
container.addView(createHeart(x, y,false,baseDelay));
}
baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay
}
// 绘制左边框
private void drawLeftBorder() {
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int spacing = 40;
AnimatorSet leftBorderAnimatorSet = new AnimatorSet();
for (int i = 0; i < screenHeight / spacing + 1; i++) {
float x = 0;
float y = i * spacing;
container.addView(createHeart(x, y,true,baseDelay));
}
baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay
}
// 绘制右边框
private void drawRightBorder() {
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int spacing = 40;
AnimatorSet rightBorderAnimatorSet = new AnimatorSet();
for (int i = 0; i < screenHeight / spacing + 1; i++) {
float x = screenWidth - convertDpToPx(15);
float y = i * spacing;
container.addView(createHeart(x, y,true,baseDelay));
}
baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay
}
// 绘制下边框
private void drawBottomBorder() {
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int spacing = 40;
int offset = (int) convertDpToPx(15);
int baseY = (int) (screenHeight - convertDpToPx(40));
for (int i = 0; i < screenWidth / spacing + 1; i++) {
float waveOffset = (float) Math.sin(i * Math.PI / 4) * offset;
float x = i * spacing;
float y = baseY;
if (i % 2 == 1) {
y -= waveOffset;
}
container.addView( createHeart(x, y, true, baseDelay));
}
baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay
}
private void drawBottomBorderDots() {
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int spacing = 30;
int offset = (int) convertDpToPx(12);
int baseY = (int) (getResources().getDisplayMetrics().heightPixels - convertDpToPx(40)) - 20;
float phaseShift = 2.0f; // 相位偏移
for (int i = 0; i < screenWidth / spacing + 2; i++) {
float waveOffset = (float) Math.sin((i + phaseShift) * Math.PI / 4) * offset;
float x = i * spacing;
float y = baseY - waveOffset;
container.addView(createHeart(x, y,false,baseDelay));
}
baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay
// 在最后加上对 addAnimatedTextView 的延迟调用
new Handler(Looper.getMainLooper()).postDelayed(this::addAnimatedTextView,
baseDelay + animationGroupInterval); // 再等一组动画时间确保完全结束
}
//添加文本动画
private void addAnimatedTextView() {
String fullText = getResources().getString(R.string.second_words);
String[] lines = fullText.split("\n");
LinearLayout verticalContainer = new LinearLayout(this);
verticalContainer.setOrientation(LinearLayout.VERTICAL);
FrameLayout.LayoutParams containerParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
);
containerParams.leftMargin = (int) convertDpToPx(16);
containerParams.topMargin = (int) convertDpToPx(25);
verticalContainer.setLayoutParams(containerParams);
container.addView(verticalContainer);
int charDelay = 300;
AtomicInteger globalIndex = new AtomicInteger();
int totalCharCount = 0;
for (String line : lines) {
LinearLayout textContainer = new LinearLayout(this);
textContainer.setOrientation(LinearLayout.HORIZONTAL);
verticalContainer.addView(textContainer);
char[] chars = line.toCharArray();
for (int i = 0; i < chars.length; i++) {
final int index = globalIndex.getAndIncrement();
final char c = chars[i];
TextView charTextView = new TextView(this);
charTextView.setText(String.valueOf(c));
charTextView.setTextSize(12);
charTextView.setTextColor(Color.parseColor("#FF69B4"));
charTextView.setAlpha(0f);
charTextView.setScaleX(0.5f);
charTextView.setScaleY(0.5f);
textContainer.addView(charTextView);
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(1000);
animator.setStartDelay(charDelay * index);
animator.addUpdateListener(animation -> {
float value = (float) animation.getAnimatedValue();
charTextView.setAlpha(value);
charTextView.setScaleX(0.5f + 0.5f * value);
charTextView.setScaleY(0.5f + 0.5f * value);
});
animator.start();
totalCharCount++;
}
}
// 计算总延迟时间 = 最后一个字符的 startDelay + 动画持续时间 + 10ms
long totalDuration = charDelay * (totalCharCount - 1) + 1000 + 10000;
// 使用 Handler 延迟跳转
new Handler(Looper.getMainLooper()).postDelayed(() -> {
// 在这里执行跳转逻辑
startActivity(new Intent(VindicateActivity.this, VowsActivity.class));
finish();
}, totalDuration);
}
// 将 dp 转换为 px
private float convertDpToPx(float dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
getResources().getDisplayMetrics());
}
@Override
protected void onDestroy() {
container.removeAllViews();
super.onDestroy();
}
}
package com.example.lovedemo.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.example.lovedemo.R;
import com.example.lovedemo.view.CustomCombinedTextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class VowsActivity extends AppCompatActivity {
private FrameLayout container;
private int[] starResIds = {
R.drawable.a1, R.drawable.a2, R.drawable.a3,
R.drawable.a4, R.drawable.a5, R.drawable.a6,
R.drawable.a7, R.drawable.a8, R.drawable.a9,
R.drawable.a10, R.drawable.a11, R.drawable.a12,
R.drawable.a13, R.drawable.a14, R.drawable.a15,
R.drawable.a16, R.drawable.a17, R.drawable.a18, R.drawable.a19
};
private Random random = new Random();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_oath);
container = findViewById(R.id.container);
// 确保 container 已经正确绑定到布局文件中的 FrameLayout
if (container == null) {
throw new IllegalStateException("Container not found in layout");
}
addRotatingZoomingImageView();
// 创建 CustomCombinedTextView 并设置参数
CustomCombinedTextView textView = new CustomCombinedTextView(this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
);
params.topMargin = 50; // 可以根据需要调整位置
params.leftMargin = 0; // 可以根据需要调整位置
textView.setLayoutParams(params);
// 添加到 container 布局中
container.addView(textView);
// 启动组合动画
textView.startCombinedAnimation(100); // 每个字间隔 300ms
}
private void addRotatingZoomingImageView() {
// 创建 ImageView
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.drawable.bee);
// 设置宽高为 200px,并设置缩放类型
imageView.setLayoutParams(new FrameLayout.LayoutParams(200, 200));
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); // 防止裁剪
// 初始透明度和缩放
imageView.setAlpha(0f);
imageView.setScaleX(0.5f);
imageView.setScaleY(0.5f);
// 初始位置设为屏幕外(左上角外侧)
float startX = 0;
float startY = 0;
imageView.setX(startX);
imageView.setY(startY);
// 添加到容器
container.addView(imageView);
// 启动动画
startTranslateAndZoomAnimation(imageView);
}
private void startTranslateAndZoomAnimation(ImageView imageView) {
float endX = 100; // 最终位置 x
float endY = 50; // 最终位置 y
// 缩放动画
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(imageView, "scaleX", 0.5f, 1f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(imageView, "scaleY", 0.5f, 1f);
// 平移动画
ObjectAnimator translateXAnim = ObjectAnimator.ofFloat(imageView, "x", -200, endX);
ObjectAnimator translateYAnim = ObjectAnimator.ofFloat(imageView, "y", 0, endY);
// 透明度动画
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
// 组合动画
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(scaleXAnim, scaleYAnim, translateXAnim, translateYAnim, alphaAnim);
animatorSet.setDuration(2500);
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
// 动画监听器
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
System.out.println("平移+缩放动画已完成");
startFallingStarAnimation(endX + 150, endY); // 在原图右侧开始掉星星
}
});
// 启动动画
animatorSet.start();
}
private void startFallingStarAnimation(float startX, float startY) {
final int STAR_COUNT = 90;
final List<ImageView> stars = new ArrayList<>();
final Handler handler = new Handler();
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenHeight = displayMetrics.heightPixels;
float finalY = screenHeight - 100;
for (int i = 0; i < STAR_COUNT; i++) {
final int index = i;
handler.postDelayed(() -> {
ImageView starView = new ImageView(this);
starView.setImageResource(starResIds[random.nextInt(starResIds.length)]);
starView.setLayoutParams(new FrameLayout.LayoutParams(50, 50));
starView.setX(startX + index * 40); // x轴偏移避免重叠
starView.setY(startY);
starView.setPivotX(50); // 100x100 图片的一半
starView.setPivotY(50);
container.addView(starView);
stars.add(starView);
// 下落动画
ObjectAnimator fallAnim = ObjectAnimator.ofFloat(starView, "y", startY, finalY);
fallAnim.setDuration(1000);
fallAnim.setInterpolator(new AccelerateInterpolator());
// 第一次弹跳
ObjectAnimator bounceAnim1 = ObjectAnimator.ofFloat(starView, "y", finalY, finalY - 100);
bounceAnim1.setDuration(500);
bounceAnim1.setInterpolator(new DecelerateInterpolator());
// 第二次弹跳
ObjectAnimator bounceAnim2 = ObjectAnimator.ofFloat(starView, "y", finalY - 100, finalY - 50);
bounceAnim2.setDuration(300);
bounceAnim2.setInterpolator(new DecelerateInterpolator());
// 组合动画:下落 + 弹跳
AnimatorSet fallBounceSet = new AnimatorSet();
fallBounceSet.playSequentially(fallAnim, bounceAnim1, bounceAnim2);
// 心形动画监听器
fallBounceSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animateStarsToHeartShape(starView, index, STAR_COUNT); // 使用固定总数
}
});
fallBounceSet.start();
}, i * 600); // 控制每颗星星之间的延迟
}
}
private void animateStarsToHeartShape(ImageView star, int index, int totalStars) {
// 获取屏幕中心坐标
float centerX = getResources().getDisplayMetrics().widthPixels / 2f;
float centerY = getResources().getDisplayMetrics().heightPixels / 2f;
// 调整该值来控制心形的大小
float scale = 15f;
// 调整t的计算方法,使得心形平滑
double t = Math.PI * 2 * index / totalStars;
// 使用心形方程来生成心形的点
double heartX = 16 * Math.pow(Math.sin(t), 3);
double heartY = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
// 归一化 + 缩放 + 居中
float targetX = (float) (heartX * scale + centerX);
float targetY = (float) (-heartY * scale + centerY); // y轴方向翻转
// 设置星星的初始位置到目标位置,不再进行动画移动
star.setX(targetX);
star.setY(targetY);
// 缩放动画(星星逐渐缩小)
ObjectAnimator scaleX = ObjectAnimator.ofFloat(star, "scaleX", 1.5f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(star, "scaleY", 1.5f, 1f);
// 旋转动画(星星飞行过程中有旋转效果)
ObjectAnimator rotate = ObjectAnimator.ofFloat(star, "rotation", 0f, 360f);
// 动画集合
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(scaleX, scaleY);
// 设置动画的持续时间和延迟
animatorSet.setDuration(800);
animatorSet.setStartDelay(index * 20L); // 使得星星逐渐填充
animatorSet.setInterpolator(new DecelerateInterpolator());
animatorSet.start();
}
}我想在这个页面添加一首歌进行播放,可以实现这个三个每个页面跳转之后继续播放吗