快过年了,写个除夕倒计时软件

904 阅读22分钟

image.png

获取今日日期

//今天日期
tvDay.setText("今天是" + TimeUtils.dateToString(TimeUtils.getTimeStame(), "yyyy年MM月dd日"));

时间转换工具类

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class TimeUtils {
    public static String dateFormat_day = "HH:mm";
    public static String dateFormat_month = "MM-dd";

    /**
     * 时间转换成字符串,默认为"yyyy-MM-dd HH:mm:ss"
     *
     * @param time 时间
     */
    public static String dateToString(long time) {
        return dateToString(time, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 时间转换成字符串,指定格式
     *
     * @param time   时间
     * @param format 时间格式
     */
    public static String dateToString(long time, String format) {
        Date date = new Date(time);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    public static Date parseServerTime(String serverTime, String format) {
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.CHINESE);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        Date date = null;
        try {
            date = sdf.parse(serverTime);
        } catch (Exception e) {
        }
        return date;
    }

    /**
     * 将时间转换为时间戳
     */
    public static String dateToStamp(String s) throws ParseException {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }

    /**
     * 将时间转换为时间戳
     */
    public static String dateToStamp2(String s) throws ParseException {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }

    /**
     * 获取当前的时间戳
     *
     * @return
     */
    public static long getTimeStame() {
        //获取当前的毫秒值
        long time = System.currentTimeMillis();
        //将毫秒值转换为String类型数据
        long time_stamp = time;
        //返回出去
        return time_stamp;
    }
}

星期获取

build.gradle中导入lunar三方库

dependencies {
   ...
    //lunar
    implementation libs.lunar
}

gradle/libs.versions.toml中

[versions]
...
lunar = "1.3.14"

[libraries]
...
lunar = { module = "cn.6tail:lunar", version.ref = "lunar" }
private Lunar lunar;
...
//当前时间
lunar = Lunar.fromDate(new Date());
//星期几
tvWeek.setText("星期" + lunar.getWeekInChinese());

天干地支、生肖、农历获取

//农历
tvNongli.setText(lunar.getYearInGanZhi() + "(" + lunar.getYearShengXiao() + ")年" + lunar.getMonthInChinese() + "月" + lunar.getDayInChinese());

灯笼布局显示字体提示

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp">

    <TextView
        android:id="@+id/tvJu"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:background="@drawable/denglong"
        android:gravity="center"
        android:paddingBottom="2dp"
        android:textColor="#FDCD7A"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvLi"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="-10dp"
        android:layout_toEndOf="@id/tvJu"
        android:background="@drawable/denglong"
        android:gravity="center"
        android:paddingBottom="2dp"
        android:textColor="#FDCD7A"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvChu"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="-10dp"
        android:layout_toEndOf="@id/tvLi"
        android:background="@drawable/denglong"
        android:gravity="center"
        android:paddingBottom="2dp"
        android:textColor="#FDCD7A"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvXi"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="-10dp"
        android:layout_toEndOf="@id/tvChu"
        android:background="@drawable/denglong"
        android:gravity="center"
        android:paddingBottom="2dp"
        android:textColor="#FDCD7A"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvHai"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="-10dp"
        android:layout_toEndOf="@id/tvXi"
        android:background="@drawable/denglong"
        android:gravity="center"
        android:paddingBottom="2dp"
        android:textColor="#FDCD7A"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvYou"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="-10dp"
        android:layout_toEndOf="@id/tvHai"
        android:background="@drawable/denglong"
        android:gravity="center"
        android:paddingBottom="2dp"
        android:textColor="#FDCD7A"
        android:textSize="18sp"
        android:textStyle="bold" />
</RelativeLayout>

所用图片资源来源:www.iconfont.cn/

denglong.png

节日获取

//元旦节
Solar sYuandan = Solar.fromYmd(lunar.getYear(), 1, 1);
//腊八节
Lunar lLaba = Lunar.fromYmd(lunar.getYear(), 12, 8);
//北方小年
Lunar lBxiaonian = Lunar.fromYmd(lunar.getYear(), 12, 23);
//南方小年
Lunar lNxiaonian = Lunar.fromYmd(lunar.getYear(), 12, 24);
//除夕
Lunar lChuxi = Lunar.fromYmd(lunar.getYear() + 1, 1, 1);
//春节
Lunar lChunjie;
if (nowTimeY.equals(String.valueOf(lunar.getYear()))) {
    lChunjie = Lunar.fromYmd(lunar.getYear(), 1, 1);
} else {
    lChunjie = Lunar.fromYmd(lunar.getYear() + 1, 1, 1);
}
//元宵节
Lunar lYuanxiaojie = Lunar.fromYmd(lunar.getYear(), 1, 15);
//情人节
Solar sQingrenjie = Solar.fromYmd(lunar.getYear(), 2, 14);
//龙抬头
Lunar lLongtaitou = Lunar.fromYmd(lunar.getYear(), 2, 2);
//妇女节
Solar sFunvjie = Solar.fromYmd(lunar.getYear(), 3, 8);
//劳动节
Solar sLaodongjie = Solar.fromYmd(lunar.getYear(), 5, 1);
//青年节
Solar sQingnianjie = Solar.fromYmd(lunar.getYear(), 5, 4);
//端午节
Lunar lDuanwujie = Lunar.fromYmd(lunar.getYear(), 5, 5);
//儿童节
Solar sErtongjie = Solar.fromYmd(lunar.getYear(), 6, 1);
//建党节
Solar sJiandangjie = Solar.fromYmd(lunar.getYear(), 7, 1);
//建军节
Solar sJianjunjie = Solar.fromYmd(lunar.getYear(), 8, 1);
//七夕节
Lunar lQixijie = Lunar.fromYmd(lunar.getYear(), 7, 7);
//中元节
Lunar lZhongyuanjie = Lunar.fromYmd(lunar.getYear(), 7, 15);
//教师节
Solar sJiaoshijie = Solar.fromYmd(lunar.getYear(), 9, 10);
//国庆节
Solar sGuoqingjie = Solar.fromYmd(lunar.getYear(), 10, 1);
//中秋节
Lunar lZhongqiujie = Lunar.fromYmd(lunar.getYear(), 8, 15);
//重阳节
Lunar lChongyangjie = Lunar.fromYmd(lunar.getYear(), 9, 9);

节日转时间戳

long yuandan = Long.parseLong(TimeUtils.dateToStamp(sYuandan + " 00:00:00"));
long laba = Long.parseLong(TimeUtils.dateToStamp(lLaba.getSolar().toString() + " 00:00:00"));
long bxiaonian = Long.parseLong(TimeUtils.dateToStamp(lBxiaonian.getSolar().toString() + " 00:00:00"));
long nxiaonian = Long.parseLong(TimeUtils.dateToStamp(lNxiaonian.getSolar().toString() + " 00:00:00"));
long chuxi = Long.parseLong(TimeUtils.dateToStamp(lChuxi.next(-1).getSolar().toString() + " 00:00:00"));
chunjie = Long.parseLong(TimeUtils.dateToStamp(lChunjie.getSolar().toString() + " 00:00:00"));
long yuanxiaojie = Long.parseLong(TimeUtils.dateToStamp(lYuanxiaojie.getSolar().toString() + " 00:00:00"));
long qingrenjie = Long.parseLong(TimeUtils.dateToStamp(sQingrenjie + " 00:00:00"));
long longtaitou = Long.parseLong(TimeUtils.dateToStamp(lLongtaitou.getSolar().toString() + " 00:00:00"));
long funvjie = Long.parseLong(TimeUtils.dateToStamp(sFunvjie + " 00:00:00"));
long laodongjie = Long.parseLong(TimeUtils.dateToStamp(sLaodongjie + " 00:00:00"));
long qingnianjie = Long.parseLong(TimeUtils.dateToStamp(sQingnianjie + " 00:00:00"));
long duanwujie = Long.parseLong(TimeUtils.dateToStamp(lDuanwujie.getSolar().toString() + " 00:00:00"));
long ertongjie = Long.parseLong(TimeUtils.dateToStamp(sErtongjie + " 00:00:00"));
long jiandangjie = Long.parseLong(TimeUtils.dateToStamp(sJiandangjie + " 00:00:00"));
long jianjunjie = Long.parseLong(TimeUtils.dateToStamp(sJianjunjie + " 00:00:00"));
long qixijie = Long.parseLong(TimeUtils.dateToStamp(lQixijie.getSolar().toString() + " 00:00:00"));
long zhongyuanjie = Long.parseLong(TimeUtils.dateToStamp(lZhongyuanjie.getSolar().toString() + " 00:00:00"));
long jiaoshijie = Long.parseLong(TimeUtils.dateToStamp(sJiaoshijie + " 00:00:00"));
long guoqingjie = Long.parseLong(TimeUtils.dateToStamp(sGuoqingjie + " 00:00:00"));
long zhongqiujie = Long.parseLong(TimeUtils.dateToStamp(lZhongqiujie.getSolar().toString() + " 00:00:00"));
long chongyangjie = Long.parseLong(TimeUtils.dateToStamp(lChongyangjie.getSolar().toString() + " 00:00:00"));

到某节日还剩多少天计算并添加到集合

private final List<Jieri> list = new ArrayList<>();
...
list.clear();

Jieri jieri2 = new Jieri();
jieri2.setId("yuandan");
jieri2.setName("元旦节");
jieri2.setTime(yuandan - nowTimeYMD);
if (yuandan - nowTimeYMD >= 0) {
    list.add(jieri2);
}

Jieri jieri3 = new Jieri();
jieri3.setId("laba");
jieri3.setName("腊八节");
jieri3.setTime(laba - nowTimeYMD);
if (laba - nowTimeYMD >= 0) {
    list.add(jieri3);
}

Jieri jieri4 = new Jieri();
jieri4.setId("bxiaonian");
jieri4.setName("北方小年");
jieri4.setTime(bxiaonian - nowTimeYMD);
if (bxiaonian - nowTimeYMD >= 0) {
    list.add(jieri4);
}

Jieri jieri5 = new Jieri();
jieri5.setId("nxiaonian");
jieri5.setName("南方小年");
jieri5.setTime(nxiaonian - nowTimeYMD);
if (nxiaonian - nowTimeYMD >= 0) {
    list.add(jieri5);
}

Jieri jieri6 = new Jieri();
jieri6.setId("chuxi");
jieri6.setName("除夕");
jieri6.setTime(chuxi - nowTimeYMD);
if (chuxi - nowTimeYMD >= 0) {
    list.add(jieri6);
}

Jieri jieri7 = new Jieri();
jieri7.setId("chunjie");
jieri7.setName("春节");
jieri7.setTime(chunjie - nowTimeYMD);
if (chunjie - nowTimeYMD >= 0) {
    list.add(jieri7);
}

Jieri jieri8 = new Jieri();
jieri8.setId("yuanxiaojie");
jieri8.setName("元宵节");
jieri8.setTime(yuanxiaojie - nowTimeYMD);
if (yuanxiaojie - nowTimeYMD >= 0) {
    list.add(jieri8);
}

Jieri jieri9 = new Jieri();
jieri9.setId("qingrenjie");
jieri9.setName("情人节");
jieri9.setTime(qingrenjie - nowTimeYMD);
if (qingrenjie - nowTimeYMD >= 0) {
    list.add(jieri9);
}

Jieri jieri10 = new Jieri();
jieri10.setId("longtaitou");
jieri10.setName("龙抬头");
jieri10.setTime(longtaitou - nowTimeYMD);
if (longtaitou - nowTimeYMD >= 0) {
    list.add(jieri10);
}

Jieri jieri11 = new Jieri();
jieri11.setId("funvjie");
jieri11.setName("妇女节");
jieri11.setTime(funvjie - nowTimeYMD);
if (funvjie - nowTimeYMD >= 0) {
    list.add(jieri11);
}

Jieri jieri13 = new Jieri();
jieri13.setId("laodongjie");
jieri13.setName("劳动节");
jieri13.setTime(laodongjie - nowTimeYMD);
if (laodongjie - nowTimeYMD >= 0) {
    list.add(jieri13);
}

Jieri jieri14 = new Jieri();
jieri14.setId("qingnianjie");
jieri14.setName("青年节");
jieri14.setTime(qingnianjie - nowTimeYMD);
if (qingnianjie - nowTimeYMD >= 0) {
    list.add(jieri14);
}

Jieri jieri15 = new Jieri();
jieri15.setId("duanwujie");
jieri15.setName("端午节");
jieri15.setTime(duanwujie - nowTimeYMD);
if (duanwujie - nowTimeYMD >= 0) {
    list.add(jieri15);
}

Jieri jieri16 = new Jieri();
jieri16.setId("ertongjie");
jieri16.setName("儿童节");
jieri16.setTime(ertongjie - nowTimeYMD);
if (ertongjie - nowTimeYMD >= 0) {
    list.add(jieri16);
}

Jieri jieri17 = new Jieri();
jieri17.setId("jiandangjie");
jieri17.setName("建党节");
jieri17.setTime(jiandangjie - nowTimeYMD);
if (jiandangjie - nowTimeYMD >= 0) {
    list.add(jieri17);
}

Jieri jieri18 = new Jieri();
jieri18.setId("jianjunjie");
jieri18.setName("建军节");
jieri18.setTime(jianjunjie - nowTimeYMD);
if (jianjunjie - nowTimeYMD >= 0) {
    list.add(jieri18);
}

Jieri jieri19 = new Jieri();
jieri19.setId("qixijie");
jieri19.setName("七夕节");
jieri19.setTime(qixijie - nowTimeYMD);
if (qixijie - nowTimeYMD >= 0) {
    list.add(jieri19);
}

Jieri jieri20 = new Jieri();
jieri20.setId("zhongyuanjie");
jieri20.setName("中元节");
jieri20.setTime(zhongyuanjie - nowTimeYMD);
if (zhongyuanjie - nowTimeYMD >= 0) {
    list.add(jieri20);
}

Jieri jieri21 = new Jieri();
jieri21.setId("jiaoshijie");
jieri21.setName("教师节");
jieri21.setTime(jiaoshijie - nowTimeYMD);
if (jiaoshijie - nowTimeYMD >= 0) {
    list.add(jieri21);
}

Jieri jieri22 = new Jieri();
jieri22.setId("guoqingjie");
jieri22.setName("国庆节");
jieri22.setTime(guoqingjie - nowTimeYMD);
if (guoqingjie - nowTimeYMD >= 0) {
    list.add(jieri22);
}

Jieri jieri23 = new Jieri();
jieri23.setId("zhongqiujie");
jieri23.setName("中秋节");
jieri23.setTime(zhongqiujie - nowTimeYMD);
if (zhongqiujie - nowTimeYMD >= 0) {
    list.add(jieri23);
}

Jieri jieri24 = new Jieri();
jieri24.setId("chongyangjie");
jieri24.setName("重阳节");
jieri24.setTime(chongyangjie - nowTimeYMD);
if (chongyangjie - nowTimeYMD >= 0) {
    list.add(jieri24);
}

// 使用Collections.sort()方法进行升序排序
Collections.sort(list, (p1, p2) -> Long.compare(p1.getTime(), p2.getTime()));
public class Jieri {
    String id;
    String name;
    long time;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }
}

除夕倒计时计算并每秒刷新一次

update();//显示数据
//开始计时
handler.postDelayed(runnable, 1000);
//停止计时
//handler.removeCallbacks(runnable);
...
public static Handler handler = new Handler(Looper.getMainLooper());

public Runnable runnable = new Runnable() {
    @RequiresApi(api = Build.VERSION_CODES.O)
    public void run() {
        update();//获取新数据
        handler.postDelayed(this, 1000); //n秒刷新一次
    }
};

@SuppressLint("SetTextI18n")
private void update() {
        //距离除夕还剩多少天
        try {
            long chuxiDay = (Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / (1000 * 60 * 60 * 24);
            long chuxiHoue = ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / (1000 * 60 * 60)) % 24;//小时
            long chuxiMinute = ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / (1000 * 60)) % 60;//分钟
            long chuxiSecond = ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / 1000) % 60;//秒
            if (chunjie - nowTime >= -1000 * 60 * 60 * 24 && chunjie - nowTime <= 0) {
                tvJu.setText("今");
                tvLi.setText("天");
                tvChu.setText("是");
                tvXi.setText("春");
                tvHai.setText("节");
                tvYou.setText("!");
                tvChuxiDay.setText("新年快乐");
                tvChuxiHour.setText("万事如意");
            } else if ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) > 0) {
                tvJu.setText("距");
                tvLi.setText("离");
                tvChu.setText("除");
                tvXi.setText("夕");
                tvHai.setText("还");
                tvYou.setText("有");
                tvChuxiDay.setText(chuxiDay + "天");
                tvChuxiHour.setText(chuxiHoue + "小时" + chuxiMinute + "分" + chuxiSecond + "秒");
            } else {
                tvJu.setText("今");
                tvLi.setText("天");
                tvChu.setText("是");
                tvXi.setText("除");
                tvHai.setText("夕");
                tvYou.setText("!");
                tvChuxiDay.setText("新年快乐");
                tvChuxiHour.setText("万事如意");
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
}

下个春节时间

tvChunjie.setText("春节时间:" + Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getSolar().toString());

下个春节当天星期几

tvChunjieWeek.setText("星期" + Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getSolar().getWeekInChinese());

下个春节农历及生肖

tvChunjieNongli.setText(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearInGanZhi() + "(" + Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao() + ")" + "年");

下个春节生肖图片显示

if ("鼠".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.shu);
} else if ("牛".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.niu);
} else if ("虎".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.hu);
} else if ("兔".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.tu);
} else if ("龙".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.dalong);
} else if ("蛇".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.she);
} else if ("马".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.ma);
} else if ("羊".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.yang);
} else if ("猴".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.hou);
} else if ("鸡".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.ji);
} else if ("狗".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.gou);
} else if ("猪".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
    ivShengxiao.setImageResource(R.drawable.zhu);
}

其他节日显示

tvJieri1.setText("");
tvJieri2.setText("");
tvJieri3.setText("");
tvJieri4.setText("");
if (list != null && !list.isEmpty()) {
    for (int i = 0; i < list.size(); i++) {
        if (i == 0) {
            //节日1
            if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                tvJieri1.setText("今天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                tvJieri1.setText("明天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                tvJieri1.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
            }
        } else if (i == 1) {
            //节日2
            if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                tvJieri2.setText("今天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                tvJieri2.setText("明天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                tvJieri2.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
            }
        } else if (i == 2) {
            //节日3
            if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                tvJieri3.setText("今天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                tvJieri3.setText("明天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                tvJieri3.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
            }
        } else if (i == 3) {
            //节日4
            if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                tvJieri4.setText("今天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                tvJieri4.setText("明天:" + list.get(i).name);
            } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                tvJieri4.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
            }
        }
    }
}

自定义雪花背景动画

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;

import java.util.ArrayList;
import java.util.List;

/**
 * created by cwj on 2024/10/27
 * Description: 下雪动画
 */
public class FallingView extends View {

    private Context mContext;
    private AttributeSet mAttrs;

    private List<FallObject> fallObjects;

    private int viewWidth;
    private int viewHeight;

    private static final int defaultWidth = 600;//默认宽度
    private static final int defaultHeight = 1000;//默认高度
    private static final int intervalTime = 5;//重绘间隔时间

    public FallingView(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public FallingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mAttrs = attrs;
        init();
    }

    private void init() {
        fallObjects = new ArrayList<>();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = measureSize(defaultHeight, heightMeasureSpec);
        int width = measureSize(defaultWidth, widthMeasureSpec);
        setMeasuredDimension(width, height);

        viewWidth = width;
        viewHeight = height;
    }

    private int measureSize(int defaultSize, int measureSpec) {
        int result = defaultSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (fallObjects.size() > 0) {
            for (int i = 0; i < fallObjects.size(); i++) {
                //然后进行绘制
                fallObjects.get(i).drawObject(canvas);
            }
            // 隔一段时间重绘一次, 动画效果
            getHandler().postDelayed(runnable, intervalTime);
        }
    }

    // 重绘线程
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            invalidate();
        }
    };

    /**
     * 向View添加下落物体对象
     *
     * @param fallObject 下落物体对象
     * @param num
     */
    public void addFallObject(final FallObject fallObject, final int num) {
        getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                getViewTreeObserver().removeOnPreDrawListener(this);
                for (int i = 0; i < num; i++) {
                    FallObject newFallObject = new FallObject(fallObject.builder, viewWidth, viewHeight);
                    fallObjects.add(newFallObject);
                }
                invalidate();
                return true;
            }
        });
    }
}
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;

import java.util.Random;

/**
 * created by cwj on 2024/10/27
 * Description: 下雪动画设置
 */
public class FallObject {
    private int initX;
    private int initY;
    private Random random;
    private int parentWidth;//父容器宽度
    private int parentHeight;//父容器高度
    private float objectWidth;//下落物体宽度
    private float objectHeight;//下落物体高度

    public int initSpeed;//初始下降速度
    public int initWindLevel;//初始风力等级

    public float presentX;//当前位置X坐标
    public float presentY;//当前位置Y坐标
    public float presentSpeed;//当前下降速度
    private float angle;//物体下落角度

    private Bitmap bitmap;
    public Builder builder;

    private boolean isSpeedRandom;//物体初始下降速度比例是否随机
    private boolean isSizeRandom;//物体初始大小比例是否随机
    private boolean isWindRandom;//物体初始风向和风力大小比例是否随机
    private boolean isWindChange;//物体下落过程中风向和风力是否产生随机变化

    private static final int defaultSpeed = 10;//默认下降速度
    private static final int defaultWindLevel = 0;//默认风力等级
    private static final int defaultWindSpeed = 10;//默认单位风速
    private static final float HALF_PI = (float) Math.PI / 2;//π/2

    public FallObject(Builder builder, int parentWidth, int parentHeight) {
        random = new Random();
        this.parentWidth = parentWidth;
        this.parentHeight = parentHeight;
        initX = random.nextInt(parentWidth);
        initY = random.nextInt(parentHeight) - parentHeight;
        presentX = initX;
        presentY = initY;

        this.builder = builder;
        isSpeedRandom = builder.isSpeedRandom;
        isSizeRandom = builder.isSizeRandom;
        isWindRandom = builder.isWindRandom;
        isWindChange = builder.isWindChange;

        initSpeed = builder.initSpeed;
        randomSpeed();
        randomSize();
        randomWind();
    }

    private FallObject(Builder builder) {
        this.builder = builder;
        initSpeed = builder.initSpeed;
        bitmap = builder.bitmap;

        isSpeedRandom = builder.isSpeedRandom;
        isSizeRandom = builder.isSizeRandom;
        isWindRandom = builder.isWindRandom;
        isWindChange = builder.isWindChange;
    }

    public static final class Builder {
        private int initSpeed;
        private int initWindLevel;
        private Bitmap bitmap;

        private boolean isSpeedRandom;
        private boolean isSizeRandom;
        private boolean isWindRandom;
        private boolean isWindChange;

        public Builder(Bitmap bitmap) {
            this.initSpeed = defaultSpeed;
            this.initWindLevel = defaultWindLevel;
            this.bitmap = bitmap;

            this.isSpeedRandom = false;
            this.isSizeRandom = false;
            this.isWindRandom = false;
            this.isWindChange = false;
        }

        public Builder(Drawable drawable) {
            this.initSpeed = defaultSpeed;
            this.initWindLevel = defaultWindLevel;
            this.bitmap = drawableToBitmap(drawable);

            this.isSpeedRandom = false;
            this.isSizeRandom = false;
            this.isWindRandom = false;
            this.isWindChange = false;
        }

        /**
         * 设置物体的初始下落速度
         *
         * @param speed
         * @return
         */
        public Builder setSpeed(int speed) {
            this.initSpeed = speed;
            return this;
        }

        /**
         * 设置物体的初始下落速度
         *
         * @param speed
         * @param isRandomSpeed 物体初始下降速度比例是否随机
         * @return
         */
        public Builder setSpeed(int speed, boolean isRandomSpeed) {
            this.initSpeed = speed;
            this.isSpeedRandom = isRandomSpeed;
            return this;
        }

        /**
         * 设置物体大小
         *
         * @param w
         * @param h
         * @return
         */
        public Builder setSize(int w, int h) {
            this.bitmap = changeBitmapSize(this.bitmap, w, h);
            return this;
        }

        /**
         * 设置物体大小
         *
         * @param w
         * @param h
         * @param isRandomSize 物体初始大小比例是否随机
         * @return
         */
        public Builder setSize(int w, int h, boolean isRandomSize) {
            this.bitmap = changeBitmapSize(this.bitmap, w, h);
            this.isSizeRandom = isRandomSize;
            return this;
        }

        /**
         * 设置风力等级、方向以及随机因素
         *
         * @param level        风力等级(绝对值为 5 时效果会比较好),为正时风从左向右吹(物体向X轴正方向偏移),为负时则相反
         * @param isWindRandom 物体初始风向和风力大小比例是否随机
         * @param isWindChange 在物体下落过程中风的风向和风力是否会产生随机变化
         * @return
         */
        public Builder setWind(int level, boolean isWindRandom, boolean isWindChange) {
            this.initWindLevel = level;
            this.isWindRandom = isWindRandom;
            this.isWindChange = isWindChange;
            return this;
        }

        public FallObject build() {
            return new FallObject(this);
        }
    }

    /**
     * 绘制物体对象
     *
     * @param canvas
     */
    public void drawObject(Canvas canvas) {
        moveObject();
        canvas.drawBitmap(bitmap, presentX, presentY, null);
    }

    /**
     * 移动物体对象
     */
    private void moveObject() {
        moveX();
        moveY();
        if (presentY > parentHeight || presentX < -bitmap.getWidth() || presentX > parentWidth + bitmap.getWidth()) {
            reset();
        }
    }

    /**
     * X轴上的移动逻辑
     */
    private void moveX() {
        presentX += defaultWindSpeed * Math.sin(angle);
        if (isWindChange) {
            angle += (float) (random.nextBoolean() ? -1 : 1) * Math.random() * 0.0025;
        }
    }

    /**
     * Y轴上的移动逻辑
     */
    private void moveY() {
        presentY += presentSpeed;
    }

    /**
     * 重置object位置
     */
    private void reset() {
        presentY = -objectHeight;
        randomSpeed();//记得重置时速度也一起重置,这样效果会好很多
        randomWind();//记得重置一下初始角度,不然雪花会越下越少(因为角度累加会让雪花越下越偏)
    }

    /**
     * 随机物体初始下落速度
     */
    private void randomSpeed() {
        if (isSpeedRandom) {
            presentSpeed = (float) ((random.nextInt(3) + 1) * 0.1 + 1) * initSpeed;//这些随机数大家可以按自己的需要进行调整
        } else {
            presentSpeed = initSpeed;
        }
    }

    /**
     * 随机物体初始大小比例
     */
    private void randomSize() {
        if (isSizeRandom) {
            float r = (random.nextInt(10) + 1) * 0.1f;
            float rW = r * builder.bitmap.getWidth();
            float rH = r * builder.bitmap.getHeight();
            bitmap = changeBitmapSize(builder.bitmap, (int) rW, (int) rH);
        } else {
            bitmap = builder.bitmap;
        }
        objectWidth = bitmap.getWidth();
        objectHeight = bitmap.getHeight();
    }

    /**
     * 随机风的风向和风力大小比例,即随机物体初始下落角度
     */
    private void randomWind() {
        if (isWindRandom) {
            angle = (float) ((random.nextBoolean() ? -1 : 1) * Math.random() * initWindLevel / 50);
        } else {
            angle = (float) initWindLevel / 50;
        }

        //限制angle的最大最小值
        if (angle > HALF_PI) {
            angle = HALF_PI;
        } else if (angle < -HALF_PI) {
            angle = -HALF_PI;
        }
    }

    /**
     * drawable图片资源转bitmap
     *
     * @param drawable
     * @return
     */
    public static Bitmap drawableToBitmap(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(
                drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(),
                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                        : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    /**
     * 改变bitmap的大小
     *
     * @param bitmap 目标bitmap
     * @param newW   目标宽度
     * @param newH   目标高度
     * @return
     */
    public static Bitmap changeBitmapSize(Bitmap bitmap, int newW, int newH) {
        int oldW = bitmap.getWidth();
        int oldH = bitmap.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newW) / oldW;
        float scaleHeight = ((float) newH) / oldH;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, oldW, oldH, matrix, true);
        return bitmap;
    }
}

布局引用

<com.cwj.newyear.FallingView
    android:id="@+id/fallingView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="80dp" />

代码设置

//初始化一个雪花样式的fallObject
FallObject.Builder builder = new FallObject.Builder(getResources().getDrawable(R.drawable.xuehua));
FallObject fallObject = builder
        .setSpeed(5, true)
        .setSize(30, 30, true)
        .setWind(5, true, true)
        .build();
fallingView.addFallObject(fallObject, 150);//添加下落物体对象

主要完整代码

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/bj" />

    <com.cwj.newyear.FallingView
        android:id="@+id/fallingView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="80dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginStart="5dp"
        android:layout_marginEnd="5dp"
        android:background="@drawable/shape_translucence"
        android:orientation="vertical"
        android:padding="10dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tvDay"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:textColor="#FDCD7A"
                android:textSize="22sp" />

            <TextView
                android:id="@+id/tvWeek"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FDCD7A"
                android:textSize="22sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvNongli"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#FDCD7A"
                    android:textSize="20sp" />

                <RelativeLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp">

                    <TextView
                        android:id="@+id/tvJu"
                        android:layout_width="40dp"
                        android:layout_height="40dp"
                        android:background="@drawable/denglong"
                        android:gravity="center"
                        android:paddingBottom="2dp"
                        android:textColor="#FDCD7A"
                        android:textSize="18sp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/tvLi"
                        android:layout_width="40dp"
                        android:layout_height="40dp"
                        android:layout_marginStart="-10dp"
                        android:layout_toEndOf="@id/tvJu"
                        android:background="@drawable/denglong"
                        android:gravity="center"
                        android:paddingBottom="2dp"
                        android:textColor="#FDCD7A"
                        android:textSize="18sp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/tvChu"
                        android:layout_width="40dp"
                        android:layout_height="40dp"
                        android:layout_marginStart="-10dp"
                        android:layout_toEndOf="@id/tvLi"
                        android:background="@drawable/denglong"
                        android:gravity="center"
                        android:paddingBottom="2dp"
                        android:textColor="#FDCD7A"
                        android:textSize="18sp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/tvXi"
                        android:layout_width="40dp"
                        android:layout_height="40dp"
                        android:layout_marginStart="-10dp"
                        android:layout_toEndOf="@id/tvChu"
                        android:background="@drawable/denglong"
                        android:gravity="center"
                        android:paddingBottom="2dp"
                        android:textColor="#FDCD7A"
                        android:textSize="18sp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/tvHai"
                        android:layout_width="40dp"
                        android:layout_height="40dp"
                        android:layout_marginStart="-10dp"
                        android:layout_toEndOf="@id/tvXi"
                        android:background="@drawable/denglong"
                        android:gravity="center"
                        android:paddingBottom="2dp"
                        android:textColor="#FDCD7A"
                        android:textSize="18sp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/tvYou"
                        android:layout_width="40dp"
                        android:layout_height="40dp"
                        android:layout_marginStart="-10dp"
                        android:layout_toEndOf="@id/tvHai"
                        android:background="@drawable/denglong"
                        android:gravity="center"
                        android:paddingBottom="2dp"
                        android:textColor="#FDCD7A"
                        android:textSize="18sp"
                        android:textStyle="bold" />
                </RelativeLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginStart="5dp"
                android:background="@drawable/shape_tv_bg"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvChuxiDay"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:gravity="center"
                    android:textColor="#F8F2CE"
                    android:textSize="22sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/tvChuxiHour"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@drawable/shape_tv_bg"
                    android:gravity="center"
                    android:textColor="#F8F2CE"
                    android:textSize="16sp" />
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tvChunjie"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FFB8A4"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/tvChunjieWeek"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:textColor="#FFB8A4"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/tvChunjieNongli"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FFB8A4"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center_horizontal"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="一年一年又一年"
                android:textColor="#F2CB5A"
                android:textSize="20sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:text="陪你到"
                android:textColor="#F2CB5A"
                android:textSize="20sp"
                android:textStyle="bold" />

            <ImageView
                android:id="@+id/ivShengxiao"
                android:layout_width="30dp"
                android:layout_height="30dp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="年"
                android:textColor="#F2CB5A"
                android:textSize="20sp"
                android:textStyle="bold" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center_horizontal"
            android:orientation="horizontal">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvJieri1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#FED3BF"
                    android:textSize="16sp" />

                <TextView
                    android:id="@+id/tvJieri3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#FED3BF"
                    android:textSize="16sp" />
            </LinearLayout>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/fu" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tvJieri2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#FED3BF"
                    android:textSize="16sp" />

                <TextView
                    android:id="@+id/tvJieri4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#FED3BF"
                    android:textSize="16sp" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

代码实现

import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private TextView tvDay, tvWeek, tvNongli, tvChuxiDay, tvChuxiHour, tvChunjie, tvChunjieWeek,
            tvChunjieNongli, tvJieri1, tvJieri2, tvJieri3, tvJieri4, tvJu, tvLi, tvChu, tvXi, tvHai, tvYou;
    private Lunar lunar;
    private ImageView ivShengxiao;
    private long nowTime;
    private long chunjie;
    private final List<Jieri> list = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
//        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
//            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
//            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
//            return insets;
//        });

        initView();
        initData();
    }

    private void initView() {
        tvDay = findViewById(R.id.tvDay);
        tvWeek = findViewById(R.id.tvWeek);
        tvNongli = findViewById(R.id.tvNongli);
        tvChuxiDay = findViewById(R.id.tvChuxiDay);
        tvChuxiHour = findViewById(R.id.tvChuxiHour);
        tvChunjie = findViewById(R.id.tvChunjie);
        tvChunjieWeek = findViewById(R.id.tvChunjieWeek);
        tvChunjieNongli = findViewById(R.id.tvChunjieNongli);
        ivShengxiao = findViewById(R.id.ivShengxiao);
        tvJieri1 = findViewById(R.id.tvJieri1);
        tvJieri2 = findViewById(R.id.tvJieri2);
        tvJieri3 = findViewById(R.id.tvJieri3);
        tvJieri4 = findViewById(R.id.tvJieri4);
        tvJu = findViewById(R.id.tvJu);
        tvLi = findViewById(R.id.tvLi);
        tvChu = findViewById(R.id.tvChu);
        tvXi = findViewById(R.id.tvXi);
        tvHai = findViewById(R.id.tvHai);
        tvYou = findViewById(R.id.tvYou);
        FallingView fallingView = findViewById(R.id.fallingView);

        //初始化一个雪花样式的fallObject
        FallObject.Builder builder = new FallObject.Builder(getResources().getDrawable(R.drawable.xuehua));
        FallObject fallObject = builder
                .setSpeed(5, true)
                .setSize(30, 30, true)
                .setWind(5, true, true)
                .build();
        fallingView.addFallObject(fallObject, 150);//添加下落物体对象
    }

    @SuppressLint("SetTextI18n")
    private void initData() {
        update();//显示数据
        //开始计时
        handler.postDelayed(runnable, 1000);
        //停止计时
        //handler.removeCallbacks(runnable);
    }

    public static Handler handler = new Handler(Looper.getMainLooper());

    public Runnable runnable = new Runnable() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        public void run() {
            update();//获取新数据
            handler.postDelayed(this, 1000); //n秒刷新一次
        }
    };

    @SuppressLint("SetTextI18n")
    private void update() {
        shuju();
        //今天日期
        tvDay.setText("今天是" + TimeUtils.dateToString(TimeUtils.getTimeStame(), "yyyy年MM月dd日"));
        //星期几
        tvWeek.setText("星期" + lunar.getWeekInChinese());
        //农历
        tvNongli.setText(lunar.getYearInGanZhi() + "(" + lunar.getYearShengXiao() + ")年" + lunar.getMonthInChinese() + "月" + lunar.getDayInChinese());
        //距离除夕还剩多少天
        try {
            long chuxiDay = (Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / (1000 * 60 * 60 * 24);
            long chuxiHoue = ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / (1000 * 60 * 60)) % 24;//小时
            long chuxiMinute = ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / (1000 * 60)) % 60;//分钟
            long chuxiSecond = ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) / 1000) % 60;//秒
            if (chunjie - nowTime >= -1000 * 60 * 60 * 24 && chunjie - nowTime <= 0) {
                tvJu.setText("今");
                tvLi.setText("天");
                tvChu.setText("是");
                tvXi.setText("春");
                tvHai.setText("节");
                tvYou.setText("!");
                tvChuxiDay.setText("新年快乐");
                tvChuxiHour.setText("万事如意");
            } else if ((Long.parseLong(TimeUtils.dateToStamp(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).next(-1).getSolar().toString() + " 00:00:00")) - nowTime) > 0) {
                tvJu.setText("距");
                tvLi.setText("离");
                tvChu.setText("除");
                tvXi.setText("夕");
                tvHai.setText("还");
                tvYou.setText("有");
                tvChuxiDay.setText(chuxiDay + "天");
                tvChuxiHour.setText(chuxiHoue + "小时" + chuxiMinute + "分" + chuxiSecond + "秒");
            } else {
                tvJu.setText("今");
                tvLi.setText("天");
                tvChu.setText("是");
                tvXi.setText("除");
                tvHai.setText("夕");
                tvYou.setText("!");
                tvChuxiDay.setText("新年快乐");
                tvChuxiHour.setText("万事如意");
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        //下个春节时间
        tvChunjie.setText("春节时间:" + Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getSolar().toString());
        //下个春节当天星期几
        tvChunjieWeek.setText("星期" + Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getSolar().getWeekInChinese());
        //下个春节农历及生肖
        tvChunjieNongli.setText(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearInGanZhi() + "(" + Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao() + ")" + "年");
        //下个春节生肖图片显示
        if ("鼠".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.shu);
        } else if ("牛".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.niu);
        } else if ("虎".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.hu);
        } else if ("兔".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.tu);
        } else if ("龙".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.dalong);
        } else if ("蛇".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.she);
        } else if ("马".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.ma);
        } else if ("羊".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.yang);
        } else if ("猴".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.hou);
        } else if ("鸡".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.ji);
        } else if ("狗".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.gou);
        } else if ("猪".equals(Lunar.fromYmd(lunar.getYear() + 1, 1, 1).getYearShengXiao())) {
            ivShengxiao.setImageResource(R.drawable.zhu);
        }

        tvJieri1.setText("");
        tvJieri2.setText("");
        tvJieri3.setText("");
        tvJieri4.setText("");
        if (list != null && !list.isEmpty()) {
            for (int i = 0; i < list.size(); i++) {
                if (i == 0) {
                    //节日1
                    if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                        tvJieri1.setText("今天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                        tvJieri1.setText("明天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                        tvJieri1.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
                    }
                } else if (i == 1) {
                    //节日2
                    if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                        tvJieri2.setText("今天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                        tvJieri2.setText("明天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                        tvJieri2.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
                    }
                } else if (i == 2) {
                    //节日3
                    if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                        tvJieri3.setText("今天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                        tvJieri3.setText("明天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                        tvJieri3.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
                    }
                } else if (i == 3) {
                    //节日4
                    if (list.get(i).getTime() > -1000 * 60 * 60 * 24 && list.get(i).getTime() <= 0) {
                        tvJieri4.setText("今天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 0 && list.get(i).getTime() <= 1000 * 60 * 60 * 24) {
                        tvJieri4.setText("明天:" + list.get(i).name);
                    } else if (list.get(i).getTime() > 1000 * 60 * 60 * 24) {
                        tvJieri4.setText(list.get(i).getTime() / (1000 * 60 * 60 * 24) + "天后:" + list.get(i).name);
                    }
                }
            }
        }
    }

    private void shuju() {
        //当前时间
        lunar = Lunar.fromDate(new Date());
        nowTime = TimeUtils.getTimeStame();
        long nowTimeYMD;
        String nowTimeY;
        try {
            nowTimeYMD = Long.parseLong(TimeUtils.dateToStamp2(TimeUtils.dateToString(TimeUtils.getTimeStame(), "yyyy-MM-dd")));
            nowTimeY = TimeUtils.dateToString(TimeUtils.getTimeStame(), "yyyy");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        //元旦节
        Solar sYuandan = Solar.fromYmd(lunar.getYear(), 1, 1);
        //腊八节
        Lunar lLaba = Lunar.fromYmd(lunar.getYear(), 12, 8);
        //北方小年
        Lunar lBxiaonian = Lunar.fromYmd(lunar.getYear(), 12, 23);
        //南方小年
        Lunar lNxiaonian = Lunar.fromYmd(lunar.getYear(), 12, 24);
        //除夕
        Lunar lChuxi = Lunar.fromYmd(lunar.getYear() + 1, 1, 1);
        //春节
        Lunar lChunjie;
        if (nowTimeY.equals(String.valueOf(lunar.getYear()))) {
            lChunjie = Lunar.fromYmd(lunar.getYear(), 1, 1);
        } else {
            lChunjie = Lunar.fromYmd(lunar.getYear() + 1, 1, 1);
        }
        //元宵节
        Lunar lYuanxiaojie = Lunar.fromYmd(lunar.getYear(), 1, 15);
        //情人节
        Solar sQingrenjie = Solar.fromYmd(lunar.getYear(), 2, 14);
        //龙抬头
        Lunar lLongtaitou = Lunar.fromYmd(lunar.getYear(), 2, 2);
        //妇女节
        Solar sFunvjie = Solar.fromYmd(lunar.getYear(), 3, 8);
        //劳动节
        Solar sLaodongjie = Solar.fromYmd(lunar.getYear(), 5, 1);
        //青年节
        Solar sQingnianjie = Solar.fromYmd(lunar.getYear(), 5, 4);
        //端午节
        Lunar lDuanwujie = Lunar.fromYmd(lunar.getYear(), 5, 5);
        //儿童节
        Solar sErtongjie = Solar.fromYmd(lunar.getYear(), 6, 1);
        //建党节
        Solar sJiandangjie = Solar.fromYmd(lunar.getYear(), 7, 1);
        //建军节
        Solar sJianjunjie = Solar.fromYmd(lunar.getYear(), 8, 1);
        //七夕节
        Lunar lQixijie = Lunar.fromYmd(lunar.getYear(), 7, 7);
        //中元节
        Lunar lZhongyuanjie = Lunar.fromYmd(lunar.getYear(), 7, 15);
        //教师节
        Solar sJiaoshijie = Solar.fromYmd(lunar.getYear(), 9, 10);
        //国庆节
        Solar sGuoqingjie = Solar.fromYmd(lunar.getYear(), 10, 1);
        //中秋节
        Lunar lZhongqiujie = Lunar.fromYmd(lunar.getYear(), 8, 15);
        //重阳节
        Lunar lChongyangjie = Lunar.fromYmd(lunar.getYear(), 9, 9);

        try {
            long yuandan = Long.parseLong(TimeUtils.dateToStamp(sYuandan + " 00:00:00"));
            long laba = Long.parseLong(TimeUtils.dateToStamp(lLaba.getSolar().toString() + " 00:00:00"));
            long bxiaonian = Long.parseLong(TimeUtils.dateToStamp(lBxiaonian.getSolar().toString() + " 00:00:00"));
            long nxiaonian = Long.parseLong(TimeUtils.dateToStamp(lNxiaonian.getSolar().toString() + " 00:00:00"));
            long chuxi = Long.parseLong(TimeUtils.dateToStamp(lChuxi.next(-1).getSolar().toString() + " 00:00:00"));
            chunjie = Long.parseLong(TimeUtils.dateToStamp(lChunjie.getSolar().toString() + " 00:00:00"));
            long yuanxiaojie = Long.parseLong(TimeUtils.dateToStamp(lYuanxiaojie.getSolar().toString() + " 00:00:00"));
            long qingrenjie = Long.parseLong(TimeUtils.dateToStamp(sQingrenjie + " 00:00:00"));
            long longtaitou = Long.parseLong(TimeUtils.dateToStamp(lLongtaitou.getSolar().toString() + " 00:00:00"));
            long funvjie = Long.parseLong(TimeUtils.dateToStamp(sFunvjie + " 00:00:00"));
            long laodongjie = Long.parseLong(TimeUtils.dateToStamp(sLaodongjie + " 00:00:00"));
            long qingnianjie = Long.parseLong(TimeUtils.dateToStamp(sQingnianjie + " 00:00:00"));
            long duanwujie = Long.parseLong(TimeUtils.dateToStamp(lDuanwujie.getSolar().toString() + " 00:00:00"));
            long ertongjie = Long.parseLong(TimeUtils.dateToStamp(sErtongjie + " 00:00:00"));
            long jiandangjie = Long.parseLong(TimeUtils.dateToStamp(sJiandangjie + " 00:00:00"));
            long jianjunjie = Long.parseLong(TimeUtils.dateToStamp(sJianjunjie + " 00:00:00"));
            long qixijie = Long.parseLong(TimeUtils.dateToStamp(lQixijie.getSolar().toString() + " 00:00:00"));
            long zhongyuanjie = Long.parseLong(TimeUtils.dateToStamp(lZhongyuanjie.getSolar().toString() + " 00:00:00"));
            long jiaoshijie = Long.parseLong(TimeUtils.dateToStamp(sJiaoshijie + " 00:00:00"));
            long guoqingjie = Long.parseLong(TimeUtils.dateToStamp(sGuoqingjie + " 00:00:00"));
            long zhongqiujie = Long.parseLong(TimeUtils.dateToStamp(lZhongqiujie.getSolar().toString() + " 00:00:00"));
            long chongyangjie = Long.parseLong(TimeUtils.dateToStamp(lChongyangjie.getSolar().toString() + " 00:00:00"));

            list.clear();

            Jieri jieri2 = new Jieri();
            jieri2.setId("yuandan");
            jieri2.setName("元旦节");
            jieri2.setTime(yuandan - nowTimeYMD);
            if (yuandan - nowTimeYMD >= 0) {
                list.add(jieri2);
            }

            Jieri jieri3 = new Jieri();
            jieri3.setId("laba");
            jieri3.setName("腊八节");
            jieri3.setTime(laba - nowTimeYMD);
            if (laba - nowTimeYMD >= 0) {
                list.add(jieri3);
            }

            Jieri jieri4 = new Jieri();
            jieri4.setId("bxiaonian");
            jieri4.setName("北方小年");
            jieri4.setTime(bxiaonian - nowTimeYMD);
            if (bxiaonian - nowTimeYMD >= 0) {
                list.add(jieri4);
            }

            Jieri jieri5 = new Jieri();
            jieri5.setId("nxiaonian");
            jieri5.setName("南方小年");
            jieri5.setTime(nxiaonian - nowTimeYMD);
            if (nxiaonian - nowTimeYMD >= 0) {
                list.add(jieri5);
            }

            Jieri jieri6 = new Jieri();
            jieri6.setId("chuxi");
            jieri6.setName("除夕");
            jieri6.setTime(chuxi - nowTimeYMD);
            if (chuxi - nowTimeYMD >= 0) {
                list.add(jieri6);
            }

            Jieri jieri7 = new Jieri();
            jieri7.setId("chunjie");
            jieri7.setName("春节");
            jieri7.setTime(chunjie - nowTimeYMD);
            if (chunjie - nowTimeYMD >= 0) {
                list.add(jieri7);
            }

            Jieri jieri8 = new Jieri();
            jieri8.setId("yuanxiaojie");
            jieri8.setName("元宵节");
            jieri8.setTime(yuanxiaojie - nowTimeYMD);
            if (yuanxiaojie - nowTimeYMD >= 0) {
                list.add(jieri8);
            }

            Jieri jieri9 = new Jieri();
            jieri9.setId("qingrenjie");
            jieri9.setName("情人节");
            jieri9.setTime(qingrenjie - nowTimeYMD);
            if (qingrenjie - nowTimeYMD >= 0) {
                list.add(jieri9);
            }

            Jieri jieri10 = new Jieri();
            jieri10.setId("longtaitou");
            jieri10.setName("龙抬头");
            jieri10.setTime(longtaitou - nowTimeYMD);
            if (longtaitou - nowTimeYMD >= 0) {
                list.add(jieri10);
            }

            Jieri jieri11 = new Jieri();
            jieri11.setId("funvjie");
            jieri11.setName("妇女节");
            jieri11.setTime(funvjie - nowTimeYMD);
            if (funvjie - nowTimeYMD >= 0) {
                list.add(jieri11);
            }

            Jieri jieri13 = new Jieri();
            jieri13.setId("laodongjie");
            jieri13.setName("劳动节");
            jieri13.setTime(laodongjie - nowTimeYMD);
            if (laodongjie - nowTimeYMD >= 0) {
                list.add(jieri13);
            }

            Jieri jieri14 = new Jieri();
            jieri14.setId("qingnianjie");
            jieri14.setName("青年节");
            jieri14.setTime(qingnianjie - nowTimeYMD);
            if (qingnianjie - nowTimeYMD >= 0) {
                list.add(jieri14);
            }

            Jieri jieri15 = new Jieri();
            jieri15.setId("duanwujie");
            jieri15.setName("端午节");
            jieri15.setTime(duanwujie - nowTimeYMD);
            if (duanwujie - nowTimeYMD >= 0) {
                list.add(jieri15);
            }

            Jieri jieri16 = new Jieri();
            jieri16.setId("ertongjie");
            jieri16.setName("儿童节");
            jieri16.setTime(ertongjie - nowTimeYMD);
            if (ertongjie - nowTimeYMD >= 0) {
                list.add(jieri16);
            }

            Jieri jieri17 = new Jieri();
            jieri17.setId("jiandangjie");
            jieri17.setName("建党节");
            jieri17.setTime(jiandangjie - nowTimeYMD);
            if (jiandangjie - nowTimeYMD >= 0) {
                list.add(jieri17);
            }

            Jieri jieri18 = new Jieri();
            jieri18.setId("jianjunjie");
            jieri18.setName("建军节");
            jieri18.setTime(jianjunjie - nowTimeYMD);
            if (jianjunjie - nowTimeYMD >= 0) {
                list.add(jieri18);
            }

            Jieri jieri19 = new Jieri();
            jieri19.setId("qixijie");
            jieri19.setName("七夕节");
            jieri19.setTime(qixijie - nowTimeYMD);
            if (qixijie - nowTimeYMD >= 0) {
                list.add(jieri19);
            }

            Jieri jieri20 = new Jieri();
            jieri20.setId("zhongyuanjie");
            jieri20.setName("中元节");
            jieri20.setTime(zhongyuanjie - nowTimeYMD);
            if (zhongyuanjie - nowTimeYMD >= 0) {
                list.add(jieri20);
            }

            Jieri jieri21 = new Jieri();
            jieri21.setId("jiaoshijie");
            jieri21.setName("教师节");
            jieri21.setTime(jiaoshijie - nowTimeYMD);
            if (jiaoshijie - nowTimeYMD >= 0) {
                list.add(jieri21);
            }

            Jieri jieri22 = new Jieri();
            jieri22.setId("guoqingjie");
            jieri22.setName("国庆节");
            jieri22.setTime(guoqingjie - nowTimeYMD);
            if (guoqingjie - nowTimeYMD >= 0) {
                list.add(jieri22);
            }

            Jieri jieri23 = new Jieri();
            jieri23.setId("zhongqiujie");
            jieri23.setName("中秋节");
            jieri23.setTime(zhongqiujie - nowTimeYMD);
            if (zhongqiujie - nowTimeYMD >= 0) {
                list.add(jieri23);
            }

            Jieri jieri24 = new Jieri();
            jieri24.setId("chongyangjie");
            jieri24.setName("重阳节");
            jieri24.setTime(chongyangjie - nowTimeYMD);
            if (chongyangjie - nowTimeYMD >= 0) {
                list.add(jieri24);
            }

            // 使用Collections.sort()方法进行升序排序
            Collections.sort(list, (p1, p2) -> Long.compare(p1.getTime(), p2.getTime()));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

演示DEMO

app.122.city/v6bjae3d

完整代码

gitee.com/juer2017/ne…