圣诞节用安卓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>
相关推荐
Demon_Hao8 分钟前
JAVA通过Redis实现Key分区分片聚合点赞、收藏等计数同步数据库,并且通过布隆过滤器防重复点赞
java·数据库·redis
Dxy123931021612 分钟前
JS发送请求的方法详解
开发语言·javascript·ecmascript
华科易迅20 分钟前
Spring装配对象方法-注解
java·后端·spring
sw12138923 分钟前
C++中的代理模式实战
开发语言·c++·算法
難釋懷33 分钟前
Lua语法入门-条件控制、函数
开发语言·junit·lua
桌面运维家44 分钟前
Win10打印机共享故障排查:权限与网络配置详解
开发语言·网络·php
庄周的大鱼1 小时前
分析@TransactionalEventListener注解失效
java·spring·springboot·事务监听器·spring 事件机制·事务注解失效解决
Sunshine for you1 小时前
实时操作系统中的C++
开发语言·c++·算法
史蒂芬_丁1 小时前
C++深度拷贝例子
java·开发语言·c++
gregmankiw2 小时前
Nemotron架构(Mamba3+Transformer+Moe)
android·深度学习·transformer