Android 纵向双选日历

这个日历的布局分两部分,一部分是显示星期几的LinearLayout,另外就是一个RecyclerView,负责纵向滚动了。

纵向双选日历

工具类:

implementation 'com.blankj:utilcode:1.17.3'

上activity_calendar代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:padding="5dp"android:text="" /></LinearLayout><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never" />
</LinearLayout>

接下来是CalendarActivity

  1. 计算数据
  2. 可以扩展日历的点击事件和范围选择事件
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import com.blankj.utilcode.constant.TimeConstants;
import com.blankj.utilcode.util.TimeUtils;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;public class CalendarActivity extends AppCompatActivity {private RecyclerView recyclerView;private CalendarRangeAdapter calendarRangeAdapter;/*** 最大月份数*/private int maxMonth = 12;private List<DateBean> dateList = new ArrayList<>();private List<DateBean> allDateList = new ArrayList<>();private Handler handler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {initView();super.handleMessage(msg);}};@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_calendar);recyclerView = findViewById(R.id.recycler_view);new Thread() {@Overridepublic void run() {initData();};}.start();}private void initView() {GridLayoutManager manager = new GridLayoutManager(CalendarActivity.this, 7);manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {return allDateList.get(position).getType() == 0 ? 7 : 1;}});recyclerView.setLayoutManager(manager);calendarRangeAdapter = new CalendarRangeAdapter(CalendarActivity.this, allDateList);recyclerView.setAdapter(calendarRangeAdapter);calendarRangeAdapter.setOnItemSelect(new CalendarRangeAdapter.OnItemSelect() {@Overridepublic void onItemClick(int position) {}@Overridepublic void onItemRangeSelect(String startDate, String endDate) {System.out.println(startDate + "~" + endDate);}});}private void initData() {for (int i = 0; i < maxMonth; i++) {Calendar calendar = Calendar.getInstance();calendar.add(Calendar.MONTH, i);int year = calendar.get(Calendar.YEAR);int month = calendar.get(Calendar.MONTH) + 1;int maxDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);String dateString = simpleDateFormat.format(calendar.getTime());DateBean monthBean = new DateBean();monthBean.setDate(dateString.substring(0, 7));monthBean.setCanSelect(false);monthBean.setType(0);dateList.clear();dateList.add(monthBean);calendar.set(Calendar.DAY_OF_MONTH, 1);//当月第一天是周几 0是周日,1是周一 以此类推int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);//填充1号前面的空白for (int j = 0; j < dayOfWeek - 1; j++) {DateBean dateBean = new DateBean();dateBean.setCanSelect(false);dateBean.setType(1);dateBean.setDate("");dateList.add(dateBean);}for (int j = 0; j < maxDays; j++) {DateBean dateBean = new DateBean();dateBean.setType(1);dateBean.setCenterString(String.valueOf(j + 1));dateBean.setSelect(true);dateBean.setDate(year + "-" + addZero(month) + "-" + addZero(j + 1));//今天之前不可选中if (TimeUtils.getTimeSpanByNow(dateBean.getDate(), new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA), TimeConstants.DAY) < 0) {dateBean.setCenterString(String.valueOf(j + 1));dateBean.setCanSelect(false);} else {if (TimeUtils.getTimeSpanByNow(dateBean.getDate(), new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA), TimeConstants.DAY) > 0) {dateBean.setCenterString(String.valueOf(j + 1));} else {dateBean.setCenterString("今天");}dateBean.setCanSelect(true);}dateList.add(dateBean);}allDateList.addAll(dateList);}Message msg = handler.obtainMessage();handler.sendMessage(msg);}private String addZero(int text) {if (text < 10) {return "0" + text;} else {return "" + text;}}
}

上CalendarRangeAdapter代码(根据bean属性操作):

  1. 根据类型,填充月布局和日布局。
  2. 包含点击、范围选择的方法
public class CalendarRangeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {private Context context;private List<DateBean> list;private int[] selectRange = new int[2];private final int TYPE_MONTH = 0;private final int TYPE_DAY = 1;public CalendarRangeAdapter(Context context, List<DateBean> list) {this.context = context;this.list = list;initSelect();}public void initSelect() {clearSelect();}public void clearSelect() {for (int i = 0; i < list.size(); i++) {list.get(i).setSelect(false);list.get(i).setSelectRange(false);list.get(i).setBottomString("");}selectRange[0] = -1;selectRange[1] = -1;}public void notifySelect() {notifyDataSetChanged();}public void setData(List<DateBean> list) {this.list = list;notifyDataSetChanged();}@NonNull@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {RecyclerView.ViewHolder holder = null;if (viewType == 0) {//月份View view = LayoutInflater.from(context).inflate(R.layout.item_month,parent, false);holder = new MonthViewHolder(view);} else {//日期View view = LayoutInflater.from(context).inflate(R.layout.item_day,parent, false);holder = new DayViewHolder(view);}return holder;}@Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {final int fPosition = holder.getAdapterPosition();if (holder instanceof MonthViewHolder) {((MonthViewHolder) holder).tvMonth.setText(list.get(position).getDate().replace("-", "年") + "月");} else {final DayViewHolder viewHolder = (DayViewHolder) holder;viewHolder.tvCenter.setText(list.get(fPosition).getCenterString());viewHolder.tvBottom.setText(list.get(fPosition).getBottomString());if (viewHolder.llDay.getTag() instanceof View.OnClickListener){viewHolder.llDay.setOnClickListener( null);}if (list.get(fPosition).isCanSelect()) {//今天之前(不可选)if (TimeUtils.getTimeSpanByNow(list.get(position).getDate(), new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA), TimeConstants.DAY) < 0) {viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_can_not_select));} else {if (TimeUtils.getTimeSpanByNow(list.get(position).getDate(), new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA), TimeConstants.DAY) > 0) {viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_can_select));} else {viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_today));}if (list.get(fPosition).isSelect()) {viewHolder.llDay.setBackgroundColor(ContextCompat.getColor(context, R.color.color_calendar_background_select));viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_select));viewHolder.tvBottom.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_select));} else if (list.get(fPosition).isSelectRange()) {viewHolder.llDay.setBackgroundColor(ContextCompat.getColor(context, R.color.color_calendar_background_select_range));viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_select));viewHolder.tvBottom.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_select));} else {viewHolder.llDay.setBackgroundColor(ContextCompat.getColor(context, R.color.color_calendar_background_normal));}if (onItemSelect != null) {View.OnClickListener clickListener =    new View.OnClickListener() {@Overridepublic void onClick(View v) {if (selectRange[0] == -1 && selectRange[1] == -1) {selectRange[0] = fPosition;list.get(fPosition).setSelect(true);list.get(fPosition).setBottomString("开始");onItemSelect.onItemClick(fPosition);notifyDataSetChanged();} else if (selectRange[0] != -1 && selectRange[1] == -1) {onItemSelect.onItemClick(fPosition);if (fPosition < selectRange[0]) {clearSelect();selectRange[0] = fPosition;list.get(fPosition).setSelect(true);list.get(fPosition).setBottomString("开始");} else if (fPosition > selectRange[0]) {selectRange[1] = fPosition;list.get(fPosition).setSelect(true);list.get(fPosition).setBottomString("结束");for (int i = selectRange[0] + 1; i < selectRange[1]; i++) {list.get(i).setSelectRange(true);list.get(i).setBottomString("");}onItemSelect.onItemRangeSelect(list.get(selectRange[0]).getDate(), list.get(selectRange[1]).getDate());} else {clearSelect();}notifyDataSetChanged();} else {clearSelect();selectRange[0] = fPosition;list.get(fPosition).setSelect(true);list.get(fPosition).setBottomString("开始");onItemSelect.onItemClick(fPosition);notifyDataSetChanged();}}};viewHolder.llDay.setOnClickListener(clickListener);viewHolder.llDay.setTag(clickListener);}}} else {viewHolder.llDay.setBackgroundColor(ContextCompat.getColor(context, R.color.color_calendar_background_normal));viewHolder.tvCenter.setTextColor(ContextCompat.getColor(context, R.color.color_calendar_can_not_select));}}}public OnItemSelect onItemSelect;public void setOnItemSelect(OnItemSelect onItemSelect) {this.onItemSelect = onItemSelect;}public interface OnItemSelect {void onItemClick(int position);void onItemRangeSelect(String startDate, String endDate);}@Overridepublic int getItemViewType(int position) {return list.get(position).getType() == 0 ? TYPE_MONTH : TYPE_DAY;}@Overridepublic int getItemCount() {return list == null ? 0 : list.size();}class MonthViewHolder extends RecyclerView.ViewHolder {TextView tvMonth;public MonthViewHolder(View itemView) {super(itemView);tvMonth = itemView.findViewById(R.id.tv_month);}}class DayViewHolder extends RecyclerView.ViewHolder {LinearLayout llDay;TextView tvCenter;TextView tvBottom;public DayViewHolder(View itemView) {super(itemView);llDay = itemView.findViewById(R.id.ll_day);tvCenter = itemView.findViewById(R.id.tv_center);tvBottom = itemView.findViewById(R.id.tv_bottom);}}
}

DateBean代码(中间文字,底部文字,是否可选等属性):

public class DateBean {/*** 日期*/private String date;/*** 底部文字*/private String bottomString;/*** 中间文字*/private String centerString;/*** 是否可以选择*/private boolean canSelect;/*** 是否选中*/private boolean isSelect;/**是否在选中范围*/private boolean isSelectRange;/*** item type 0月份 1日期*/private int type;public String getDate() {return date == null ? "" : date;}public void setDate(String date) {this.date = date;}public String getCenterString() {return centerString == null ? "" : centerString;}public void setCenterString(String centerString) {this.centerString = centerString;}public boolean isCanSelect() {return canSelect;}public void setCanSelect(boolean canSelect) {this.canSelect = canSelect;}public boolean isSelect() {return isSelect;}public void setSelect(boolean select) {isSelect = select;}public boolean isSelectRange() {return isSelectRange;}public void setSelectRange(boolean selectRange) {isSelectRange = selectRange;}public int getType() {return type;}public void setType(int type) {this.type = type;}public String getBottomString() {return bottomString == null ? "" : bottomString;}public void setBottomString(String bottomString) {this.bottomString = bottomString;}
}

上color.xml(可以自己换):

<resources><color name="color_calendar_can_not_select">#dedede</color><color name="color_calendar_can_select">#505050</color><color name="color_calendar_select">#ffffff</color><color name="color_calendar_today">#F67332</color><color name="color_calendar_background_select">#F3BE30</color><color name="color_calendar_background_select_range">#7DF3BE30</color><color name="color_calendar_background_normal">#00000000</color>
</resources>

OK,完毕!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/626433.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter测试学习笔记

第一章 jmeter基础知识 一.Jmeter工具中的组件 1.测试计划&#xff1a;Jmeter测试的起点。容器。 2.线程组&#xff1a;代表一定的用户 3.取样器&#xff1a;发送请求的最小单元 4.逻辑控制器&#xff1a;处理请求逻辑 5.前置处理器&#xff1a;请求之前的操作 6.后置处…

vue3推荐算法

Vue 3 推荐算法主要指的是在 Vue 3 框架中实现的或者适用于 Vue 3 的算法库或组件库。Vue 3 由于其优秀的设计和性能&#xff0c;被广泛应用于构建各种类型的应用程序&#xff0c;包括需要复杂算法支持的项目。以下是一些在 Vue 3 中可能会用到的推荐算法资源&#xff1a; Vue-…

【leetcode】双指针算法技巧——滑动窗口

标题&#xff1a;【leetcode】双指针算法技巧——滑动窗口 水墨不写bug 正文开始&#xff1a; 滑动窗口介绍 滑动窗口是一种常用的算法技巧&#xff0c;用于解决一些涉及 连续子数组或子串 的问题。它的基本思想是 维护一个窗口&#xff0c;通过 在窗口内移动 来寻找满…

图灵奖得主AviWigderson:随机性与AI深度融合,引领计算科学新篇章

近日&#xff0c;理论计算机科学领域的杰出代表Avi Wigderson教授荣获了享有“计算机界诺贝尔奖”美誉的图灵奖&#xff0c;以表彰他对计算中随机性和伪随机性研究的杰出贡献。这一荣誉不仅彰显了Wigderson教授在计算理论领域的卓越成就&#xff0c;也为当前热门的AI和深度学习…

嵌入式中C++指针使用方法总结

各位开发者大家好,在分享指针之前,先来看一下int *p[3]和int (*p)[3] 的区别。 int *p[3] p是一个数组,此数组有3个元素,每个元素都是int*类型,也就是指向整型数据的指针类型。 int a=10,b=20,c=30; int*p[3]={&a,&b,&c}; 而int(*p)[3]中的p是一个指向数组的…

强强联手|AI赋能智能工业化,探索AI在工业领域的应用

随着人工智能&#xff08;AI&#xff09;技术的不断发展和应用&#xff0c;AI在各个领域展现出了巨大的潜力和价值。在工业领域&#xff0c;AI的应用也越来越受到关注。AI具备了丰富的功能和强大的性能&#xff0c;为工业领域的发展带来了巨大的机遇和挑战。 一站式软件外包、项…

python使用redis存储时序数据

import redisdef ts_demo():"""时序数据存储RedisTimeSeries测试"""# 连接到Redisr redis.Redis(hostlocalhost, password"xxxx", port63790, db0)r1 r.ts()# print(r1.get("ts_key"))# print(r.exists(ts_key))# # 清空键…

链动3+1模式相比传统商业模式有何优势?

链动31模式是一种创新的商业模式&#xff0c;它结合了身份机制、直推奖励和团队奖励等策略。该模式通过设定代理和老板两种身份&#xff0c;构建了一个清晰的裂变链条。用户可以通过推荐新用户加入来获得奖励&#xff0c;并实现身份的升级。 假设有一个电商平台采用了链动31模…

linux离线安装MySql

一、mysql离线安装包下载 地址&#xff1a;MySQL. 点击DOWNLOADS&#xff0c;点击下图链接 点击Community Server Select Version 版本下拉框选择有两个选择 8.3.0 Innovation 是创新版&#xff0c;8.0.36是稳定版本&#xff0c;选择8.0.36 Select Operating System 操作系…

【光伏科普】光伏软件都有些什么功能?

光伏软件是为满足光伏行业特定需求而设计的工具&#xff0c;它涵盖了多个方面的功能&#xff0c;以支持光伏系统的设计、分析、优化和运营。以下是光伏软件通常具备的一些核心功能&#xff1a; 1.光伏系统设计 组件布局优化&#xff1a;根据地理位置、光照条件、阴影遮挡等因素…

cowa新的数据筛选代码

cowa新的数据筛选代码 代码地址&#xff1a; https://git.cowarobot.com/lhb/data_extracting 一阶段筛选 修改配置文件 config/common_stage.yamlversion: 3 services:de:image: harbor.cowarobot.cn/lhb/data:crpilot2.5-torch2.2environment:- CRPILOT_INSTALL_VERSIONx86…

接口压力测试 jmeter--入门篇(一)

一 压力测试的目的 评估系统的能力识别系统的弱点&#xff1a;瓶颈/弱点检查系统的隐藏的问题检验系统的稳定性和可靠性 二 性能测试指标以及测算 【虚拟用户数】&#xff1a;线程用户【并发数】&#xff1a;指在某一时间&#xff0c;一定数量的虚拟用户同时对系统的某个功…