andorid 日历选择器

 先看效果图:


主要代码 

package com.example.fly

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date

class JCalendarView@JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr){
    private var lastTv: ImageView? = null
    private  var nextTv:ImageView? = null
    private var dateTv: TextView? = null
    private  var nowTv:TextView? = null
    private var calendarRv: RecyclerView? = null
    private val addYear = 0

    private var mAdapter: CalendarAdapter=CalendarAdapter()
    @SuppressLint("SimpleDateFormat")
    private val sdf = SimpleDateFormat("yyyy-MM-dd") //日期格式化

    private val mCalendar = Calendar.getInstance() //日历控件初始化

    init {
        initView(context)
    }

    private fun initView(context: Context) {
        val inflater = LayoutInflater.from(context)
        inflater.inflate(R.layout.layout_calendar, this)
        lastTv = findViewById(R.id.lastTv)
        nextTv = findViewById(R.id.nextTv)
        dateTv = findViewById(R.id.dateTv)
        calendarRv = findViewById(R.id.recyclerView)
        nowTv = findViewById(R.id.tv_now)
        calendarRv!!.layoutManager = GridLayoutManager(context, 7)
        calendarRv!!.adapter = mAdapter
        initData()
        nowTv!!.setOnClickListener { v: View? ->
            val date = Date()
            mCalendar.time = date
            val datess = sdf.format(date)
            mAdapter.setSelectDate(Integer.valueOf(datess.substring(8)))
            initData()
        }
        nextTv!!.setOnClickListener { v: View? ->
            mCalendar.add(Calendar.MONTH, +1) //月份+1
            initData()
        }
        //“上一个”点击事件
        lastTv!!.setOnClickListener { v: View? ->
            mCalendar.add(Calendar.MONTH, -1) //月份-1
            initData()
        }
    }

    @SuppressLint("SetTextI18n")
    private fun initData() {
        val datess = sdf.format(mCalendar.time)
        dateTv!!.text ="${datess.substring(0, 4)} | ${datess.substring(5, 7)} . ${datess.substring(8) }"
        val cells = ArrayList<Date>()
        val calendar = mCalendar.clone() as Calendar //克隆日历对象
        calendar[Calendar.DAY_OF_MONTH] = 1 //置于当月第一天;
        val prevDays = calendar[Calendar.DAY_OF_WEEK] - 1 //获取上个月最后一天是星期几
        calendar.add(Calendar.DAY_OF_MONTH, -prevDays) //第一天
//        //获取每月有几周
//        int actualMaximum = calendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
//        int maxCount = actualMaximum * 7;  //设置每个月最大天数
        //循环存入集合中
        while (cells.size < 35) {
            cells.add(calendar.time)
            calendar.add(Calendar.DAY_OF_MONTH, 1) //日期+1
        }
        //判断当月的最后一天是否在集合里面
        val cal = mCalendar.clone() as Calendar
        cal.add(Calendar.MONTH, 0)
        cal[Calendar.DAY_OF_MONTH] = cal.getActualMaximum(Calendar.DAY_OF_MONTH)
        val preMonth = cal.time
        if (!cells.contains(preMonth)) {
            for (i in 0..6) {
                cells.add(calendar.time)
                calendar.add(Calendar.DAY_OF_MONTH, 1)
            }
        }
        mAdapter.submitList(cells)
        mAdapter.setmListener(object : CalendarAdapter.OnItemClickListener {
            override fun onItemClick(v: View?, position: Int, data: String?) {
                dateTv!!.text ="${data!!.substring(0, 4)} | ${data.substring(5, 7)} . ${data.substring(8) }"
            }

        })
    }
}

class CalendarAdapter : RecyclerView.Adapter<CalendarAdapter.ViewHolder>() {
    private var mList: List<Date> = ArrayList()
    private var mSelectPosition = -1

    // 创建一个接口来处理点击事件
    interface OnItemClickListener {
        fun onItemClick(v: View?, position: Int, data: String?)
    }

    private var mDay = 0
    private var mListener: OnItemClickListener? = null
    fun setmListener(mListener: OnItemClickListener?) {
        this.mListener = mListener
    }


    @SuppressLint("NotifyDataSetChanged")
    fun submitList(list: List<Date>) {
        mList = list
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.item_calendar, parent, false)
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        @SuppressLint("SimpleDateFormat")
        val mDate = SimpleDateFormat("yyyy-MM-dd").format(mList[position])
        //2023-11-13
        val day = mDate.substring(8).toInt()
        val month = mDate.substring(5, 7).toInt()
        val year = mDate.substring(0, 4).toInt()
        var isTheSameMonth = false //是否与当前月份相同
        if (month == getNowMonth()) {  //月份相同
            isTheSameMonth = true
        }

        //若显示的日期月份与当前月份相同,则设置字体颜色是黑色
        if (isTheSameMonth) {
            holder.itemTv.setTextColor(Color.parseColor("#333333"))
        } else {
            holder.itemTv.setTextColor(Color.parseColor("#999999"))
        }
        if (day == 1) {
            if (month == getNowMonth()) {
                holder.itemTv.setText(getNowMonth().toString() + "月")
            } else {
                val months: Int = getNowMonth() + 1
                holder.itemTv.text = if (months > 12) 1.toString() + "月" else months.toString() + "月"
            }
            holder.itemTv.setTextColor(Color.parseColor("#E71421"))
        } else {
            holder.itemTv.text = day.toString()
        }

        //设置当前日期字体为红色
        if (getNowDay() == day && getNowMonth() == month && getNowYear() == year) {
            holder.itemTv.setTextColor(Color.parseColor("#E71421"))
            holder.layout.setBackgroundResource(R.drawable.shape_ffe2e1_rounded_20dp)
        } else {
            holder.layout.setBackgroundColor(Color.WHITE)
        }
        if (position == mSelectPosition) {
            holder.itemTv.setTextColor(Color.parseColor("#ffffff"))
            holder.layout.setBackgroundResource(R.drawable.shape_e71421_rounded_20dp)
        }
        if (day == mDay) {
            holder.itemTv.setTextColor(Color.parseColor("#ffffff"))
            holder.layout.setBackgroundResource(R.drawable.shape_e71421_rounded_20dp)
        }
        holder.layout.setOnClickListener { v: View? ->
//                    setSelectPostion(position);
            setSelectDate(day)
            mListener?.onItemClick(v, position, mDate)
        }
    }

    override fun getItemCount(): Int {
        return mList.size
    }

    @SuppressLint("NotifyDataSetChanged")
    fun setSelectPostion(postion: Int) {
        mSelectPosition = postion
        notifyDataSetChanged()
    }

    @SuppressLint("NotifyDataSetChanged")
    fun setSelectDate(day: Int) {
        mDay = day
        notifyDataSetChanged()
    }

    private fun getNowYear(): Int {
        val calendar = Calendar.getInstance()
        return calendar[Calendar.YEAR]
    }

    private fun getNowMonth(): Int {
        val calendar = Calendar.getInstance()
        return calendar[Calendar.MONTH] + 1
    }

    private fun getNowDay(): Int {
        val calendar = Calendar.getInstance()
        return calendar[Calendar.DAY_OF_MONTH]
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var itemTv: TextView
        var layout: LinearLayout

        init {
            itemTv = itemView.findViewById(R.id.itemTv)
            layout = itemView.findViewById(R.id.llayout)
        }
    }
}

布局文件

1、layout_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:gravity="center"
    android:orientation="vertical"
    android:padding="16dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
        <TextView
            android:id="@+id/dateTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="2022年11月"
            android:layout_gravity="center"
            android:textColor="#333"
            android:textSize="14sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/tv_now"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="回到今天"
            android:textColor="#999"
            android:layout_gravity="center"
            android:layout_marginStart="24dp"
            android:textSize="14sp"
            android:textStyle="bold" />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="#999"
            android:layout_gravity="center"
            android:layout_marginStart="24dp"
            android:textSize="14sp"
            android:textStyle="bold" />

        <ImageView
            android:id="@+id/lastTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/icon_gengduo"
            android:paddingStart="16dp"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            android:rotation="180"
            android:layout_marginEnd="8dp"
            />
        <ImageView
            android:id="@+id/nextTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/icon_gengduo"
            android:paddingEnd="16dp"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            />

    </LinearLayout>



    <LinearLayout
        android:id="@+id/weekLl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/Tv1"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="日"
            android:textColor="#999"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/Tv2"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="一"
            android:textColor="#999"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/Tv3"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="二"
            android:textColor="#999"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/Tv4"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="三"
            android:textColor="#999"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/Tv5"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="四"
            android:textColor="#999"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/Tv6"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="五"
            android:textColor="#999"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/Tv7"
            android:layout_width="0dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="六"
            android:textColor="#999"
            android:textSize="14sp" />
    </LinearLayout>


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center" />

</LinearLayout>

2、item_calendar

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/llayout"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/itemTv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="1"
        android:textColor="#999"
        android:textSize="14sp" />

</LinearLayout>

3、shape:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
 <solid android:color="#e71421"/>
    <corners android:radius="20dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <corners android:radius="20dp" />
  <solid android:color="#ffe2e1" />
</shape>

欢迎大家指正不足的地方;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值