ChristmasTreeView.java
package com.example.redpacket;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class ChristmasTreeView extends View {
private Paint paint;
private int x, y; // 坐标
private boolean isRunning = false; // 控制动画开关
public ChristmasTreeView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
paint.setColor(Color.GREEN);
x = 380; // 树的基本横坐标
y = 100; // 树的起始纵坐标
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawTree(canvas);
}
private void drawTree(Canvas canvas) {
// 绘制每一层三角形
drawTriangle(canvas, 1, 4); // 第一层(顶部)
drawTriangle(canvas, 3, 6); // 第二层
drawTriangle(canvas, 5, 8); // 第三层
drawTriangle(canvas, 7, 10); // 第四层
drawTriangle(canvas, 9, 12); // 第五层
// 绘制树根
drawRoot(canvas);
}
private void drawTriangle(Canvas canvas, int from, int to) {
int baseWidth = 20; // 每层的基础宽度
for (int i = from; i <= to; i++) {
paint.setColor(Color.rgb(9, 124, 37)); // 树绿色
int currentWidth = (i * 2 - 1) * baseWidth; // 当前层的宽度计算
// 绘制三角形
for (int j = 0; j < currentWidth; j += baseWidth) {
canvas.drawRect(x - currentWidth / 2 + j, y, x - currentWidth / 2 + j + baseWidth, y + baseWidth, paint);
}
y += baseWidth; // 向下移动
}
x = 380; // 重置 x 以对齐
}
private void drawRoot(Canvas canvas) {
paint.setColor(Color.rgb(131, 78, 0)); // 棕色根部
x = 380 - 22; // 重置 x 以对齐树根
y += 10; // 向下调整根部位置(根据需要调整)
// 绘制根
for (int i = 0; i < 4; i++) { // 根部高度
for (int j = 0; j < 3; j++) { // 根部宽度
canvas.drawRect(x, y, x + 20, y + 20, paint);
x += 22; // 向右移动画出根部的部分
}
x = 380 - 22; // 确保根部对齐
y += 20; // 向下移动
}
}
public void toggleAnimation() {
isRunning = !isRunning;
invalidate(); // 请求重绘
}
public boolean isRunning() {
return isRunning;
}
}
main
package com.example.redpacket;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private Button onOffButton;
private MediaPlayer mediaPlayer;
private RelativeLayout mainLayout; // 主要布局
private List<ImageView> redPacketImages = new ArrayList<>(); // 红包列表
private boolean isRunning = false; // 是否显示红包雨
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
onOffButton = findViewById(R.id.on_off_button);
mediaPlayer = MediaPlayer.create(this, R.raw.music);
mainLayout = findViewById(R.id.main_layout); // 获取主布局
onOffButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isRunning) {
stopRedPacketRain();
onOffButton.setText("Start Red Packet Rain");
} else {
startRedPacketRain();
onOffButton.setText("Stop Red Packet Rain");
}
}
});
}
private void startRedPacketRain() {
isRunning = true;
mediaPlayer.start();
mediaPlayer.setLooping(true);
final int screenWidth = mainLayout.getWidth();
// 创建红包降落线程
new Thread(new Runnable() {
@Override
public void run() {
while (isRunning) {
runOnUiThread(new Runnable() {
@Override
public void run() {
createRedPacket(screenWidth);
}
});
try {
Thread.sleep(200); // 控制生成红包的速度
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private void createRedPacket(int screenWidth) {
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.red_packet));
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(100, 100);// 将大小改为100x100
layoutParams.topMargin = -100; // 从上方开始
layoutParams.leftMargin = new Random().nextInt(screenWidth - 100);
imageView.setLayoutParams(layoutParams);
mainLayout.addView(imageView); // 添加红包视图
redPacketImages.add(imageView);
moveRedPacket(imageView);
}
private void moveRedPacket(final ImageView imageView) {
new Thread(new Runnable() {
@Override
public void run() {
int currentY = -50; // 开始位置
final int screenHeight = ((RelativeLayout) imageView.getParent()).getHeight();
while (currentY < screenHeight && isRunning) {
int finalCurrentY = currentY;
runOnUiThread(new Runnable() {
@Override
public void run() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
params.topMargin = finalCurrentY;
imageView.setLayoutParams(params);
}
});
currentY += 10; // 每次移动10像素
try {
Thread.sleep(50); // 每50毫秒更新位置
} catch (InterruptedException e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (redPacketImages.contains(imageView)) {
imageView.setVisibility(View.GONE);
redPacketImages.remove(imageView);
}
}
});
}
}).start();
}
private void stopRedPacketRain() {
isRunning = false;
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
for (ImageView imageView : redPacketImages) {
imageView.setVisibility(View.GONE);
}
redPacketImages.clear();
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/on_off_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Red Packet Rain"/>
<com.example.redpacket.ChristmasTreeView
android:id="@+id/christmas_tree_view"
android:layout_width="match_parent"
android:layout_height="685dp"
android:layout_below="@id/on_off_button"
android:layout_gravity="center"
android:layout_marginTop="69dp" />
</RelativeLayout>