圣诞节用安卓java画一棵圣诞树

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>
相关推荐
南宫生2 分钟前
力扣-图论-70【算法学习day.70】
java·学习·算法·leetcode·图论
zfj3212 分钟前
java日志框架:slf4j、jul(java.util.logging)、 log4j、 logback
java·log4j·logback·java日志框架·slf4j·jul
程序猿阿伟9 分钟前
《探索 Apache Spark MLlib 与 Java 结合的卓越之道》
java·spark-ml·apache
一條狗14 分钟前
隨筆 20241224 ts寫入excel表
开发语言·前端·typescript
向阳121818 分钟前
sentinel来源访问控制(黑白名单)
java·sentinel
Takumilove18 分钟前
MQTT入门:在Spring Boot中建立连接及测试
java·spring boot·后端
yayaya15227 分钟前
javaScriptBOM
开发语言·javascript·ecmascript
潜洋31 分钟前
Spring Boot 教程之三十六:实现身份验证
java·数据库·spring boot
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭35 分钟前
C#都可以找哪些工作?
开发语言·c#
TroubleMaker43 分钟前
OkHttp源码学习之retryOnConnectionFailure属性
android·java·okhttp