创建日期对象
// valid 代表是否是有效数据
class Day(var valid : Boolean, var year : Int ,var month : Int ,var day : Int)
xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:orientation="vertical"
android:paddingHorizontal="@dimen/dp_20">
<com.hjq.shape.layout.ShapeFrameLayout
android:id="@+id/shapeFrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_20"
app:shape_radius="@dimen/dp_100"
app:shape_solidColor="#C3FF44">
<com.hjq.shape.view.ShapeImageView
android:id="@+id/left"
android:layout_width="@dimen/dp_40"
android:layout_height="@dimen/dp_40"
android:layout_gravity="center_vertical"
android:padding="@dimen/dp_6"
android:scaleX="-1"
android:src="@mipmap/my_left_arrow"
app:shape_radius="@dimen/dp_100"
app:shape_solidColor="@color/black" />
<TextView
android:id="@+id/monthTv"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_50"
android:gravity="center"
android:text="4月"
android:textColor="@color/black"
android:textSize="@dimen/sp_20"
android:textStyle="bold" />
<com.hjq.shape.view.ShapeImageView
android:id="@+id/right"
android:layout_width="@dimen/dp_40"
android:layout_height="@dimen/dp_40"
android:layout_gravity="end|center_vertical"
android:padding="@dimen/dp_6"
android:src="@mipmap/my_left_arrow"
app:shape_radius="@dimen/dp_100"
app:shape_solidColor="@color/black" />
</com.hjq.shape.layout.ShapeFrameLayout>
<com.hjq.shape.layout.ShapeLinearLayout
android:id="@+id/shapeLinearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:orientation="vertical"
android:paddingHorizontal="@dimen/dp_10"
android:paddingTop="@dimen/dp_10"
android:paddingBottom="@dimen/dp_20"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/shapeFrameLayout"
app:shape_radius="@dimen/dp_30"
app:shape_solidColor="#FFCFE5">
<com.hjq.shape.layout.ShapeLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingVertical="@dimen/dp_5"
app:shape_radius="@dimen/dp_100"
app:shape_solidColor="@color/white">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="日"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="一"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="二"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="三"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="四"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="五"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="六"
android:textColor="@color/black"
android:textSize="@dimen/sp_15"
android:textStyle="bold" />
</com.hjq.shape.layout.ShapeLinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/dayRecycleView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:gravity="center" />
</com.hjq.shape.layout.ShapeLinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
控件来自于控件库 ,用普通的控件也行GitHub - getActivity/ShapeView: Shape 支持在布局中直接定义啦,支持设置阴影,文字渐变色,状态选择器
在drawable中创建选中日期的样式文件 layout_onclick_style.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 设置圆角半径 -->
<corners android:radius="15dp" />
<!-- 设置边框宽度和颜色 -->
<stroke
android:width="1dp"
android:color="#00FFEE" /> <!-- 设置边框颜色 -->
</shape>
在drawable中创建未选中日期的样式文件 layout_unclick_style.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 设置圆角半径 -->
<corners android:radius="15dp" />
<!-- 设置边框宽度和颜色 -->
<stroke
android:width="1dp"
android:color="@color/white" /> <!-- 设置边框颜色 -->
</shape>
在drawable中创建今日日期的样式文件 layout_today_style.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 设置圆角半径 -->
<corners android:radius="15dp" />
<solid android:color="#00FFEE"/>
</shape>
创建适配器子项布局day_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10">
<FrameLayout
android:layout_width="@dimen/dp_30"
android:layout_height="@dimen/dp_30"
android:layout_gravity="center"
android:id="@+id/frameLayout"
android:background="@drawable/layout_unclick_style">
<TextView
android:id="@+id/timeTv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:text="1"
android:gravity="center"
android:textSize="@dimen/sp_13"
android:textColor="@color/white"/>
</FrameLayout>
</FrameLayout>
创建适配器文件 DayAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bubblesprite.flow.R
import com.bubblesprite.flow.databinding.DayItemLayoutBinding
import com.bubblesprite.flow.entity.Day
import com.bubblesprite.flow.utils.FlowUtils
import java.util.Calendar
import java.util.concurrent.Flow
class DayAdapter(val context: Context, var DayList: List<Day> ) :
RecyclerView.Adapter<DayAdapter.ViewHolder>() {
var onClickIndex = -1
interface itemOnClickListener{
fun setItemOnClickListener(timeInMillis : Long)
}
private var listener: itemOnClickListener? = null
fun setItemOnClickListener(listener: itemOnClickListener) {
this.listener = listener
}
inner class ViewHolder(binding: DayItemLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
val frameLayout = binding.frameLayout
val timeTv = binding.timeTv
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding =
DayItemLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val day = DayList[position]
if (day.valid) { //有效数据
holder.timeTv.text = day.day.toString()
val (year,month,today) = getCurrentDate()
if (onClickIndex == position){
holder.frameLayout.background = context.getDrawable(R.drawable.layout_onclick_style)
holder.timeTv.setTextColor( context.getResources().getColor(R.color.color_00FFEE))
}else{
holder.frameLayout.background = context.getDrawable(R.drawable.layout_unclick_style)
holder.timeTv.setTextColor( context.getResources().getColor(R.color.white))
}
if (day.year == year && day.month == month && day.day == today){
//如果是今天
holder.frameLayout.background = context.getDrawable(R.drawable.layout_today_style)
holder.timeTv.setTextColor( context.getResources().getColor(R.color.white))
}
holder.frameLayout.setOnClickListener {
onClickIndex = position
notifyDataSetChanged()
listener!!.setItemOnClickListener(getTimestampAtMidnight(day.year,day.month,day.day))
}
} else {
holder.frameLayout.background = null
holder.timeTv.visibility = View.GONE
}
}
fun getCurrentDate(): Triple<Int, Int, Int> {
// 创建 Calendar 对象并获取当前时间
val calendar = Calendar.getInstance()
// 获取当前的年、月、日
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH) + 1 // 月份从 0 开始,因此需要加 1
val day = calendar.get(Calendar.DAY_OF_MONTH)
// 返回年、月、日的数字
return Triple(year, month, day)
}
//获取日期的时间戳
fun getTimestampAtMidnight(year: Int, month: Int, dayOfMonth: Int): Long {
val calendar = Calendar.getInstance(TimeZone.getDefault())
calendar.set(Calendar.YEAR, year)
calendar.set(Calendar.MONTH, month - 1) // 注意:Java Calendar月份是从0开始的
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.set(Calendar.MILLISECOND, 0)
return calendar.timeInMillis
}
override fun getItemCount() = DayList.size
具体功能实现
创建全局变量
var thisYear = 0
var thisMonth = 0
创建方法
fun initAdapter(year: Int, month: Int) {
val (daysInMonth, firstDayOfWeek) = getMonthDetails(year, month)
val newDayList = ArrayList<Day>()
if (firstDayOfWeek < 7) {
for (i in 0 until firstDayOfWeek) {
newDayList.add(Day(false, 0, 0, 0))
}
}
for (i in 1..daysInMonth) {
newDayList.add(Day(true, year, month, i))
}
binding.dayRecycleView1.layoutManager = GridLayoutManager(requireContext(), 7)
val adapter = DayAdapter(requireContext(), newDayList)
adapter.setItemOnClickListener(this)
binding.dayRecycleView1.adapter = adapter
}
fun getMonthDetails(year: Int, month: Int): Pair<Int, Int> {
val calendar = Calendar.getInstance()
calendar.set(year, month - 1, 1) // 注意月份从0开始
// 获取该月的天数
val daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
// 获取该月第一天的星期数,1表示星期日,2表示星期一,以此类推
val firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
return Pair(daysInMonth, firstDayOfWeek-1)
}
fun getCurrentDate(): Triple<Int, Int, Int> {
// 创建 Calendar 对象并获取当前时间
val calendar = Calendar.getInstance()
// 获取当前的年、月、日
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH) + 1 // 月份从 0 开始,因此需要加 1
val day = calendar.get(Calendar.DAY_OF_MONTH)
// 返回年、月、日的数字
return Triple(year, month, day)
}
onCreate()方法
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val (thisYear,thisMonth,today) = getCurrentDate()
binding.monthTv.text = "$thisMonth 月"
this.thisYear = thisYear
this.thisMonth = thisMonth
initAdapter(thisYear,thisMonth)
binding.left.setOnClickListener {
if (it.isVisible){
thisMonth-=1
if (thisMonth-1 == 0){
binding.left.visibility = View.INVISIBLE
}
binding.monthTv.text = "$thisMonth 月"
binding.right.visibility = View.VISIBLE
initAdapter(thisYear,thisMonth)
}
}
binding.right.setOnClickListener {
if (it.isVisible){
thisMonth+=1
if (thisMonth+1 == 13){
binding.right.visibility = View.INVISIBLE
}
binding.monthTv.text = "$thisMonth 月"
binding.left.visibility = View.VISIBLE
initAdapter(thisYear,thisMonth)
}
}
}
使用了ViewBinding来绑定控件,不会的自己去学
日期点击事件的回调
//让你的类实现适配的itemOnClickListener接口
class Tab1Fragment : BaseFragment(),
DayAdapter.itemOnClickListener{
。。。
//实现这个方法:
override fun setItemOnClickListener(timeInMillis : Long) {
//具体的点击事件逻辑
}
}