Android Studio+Firebase实时数据库:考勤记录节假日行着色实现咨询
Hey there! Let's break down how to implement your attendance record viewing feature with holiday row coloring step by step, tailored to your Android Studio + Firebase setup:
1. 从Firebase实时数据库拉取目标考勤数据
First, we'll fetch the attendance data based on the employee ID and year the user inputs. Your database structure is Attendance Records → 员工ID → 月份 → 日期 → 考勤详情, so we need to target the specific employee's nodes, filter by the target year, and collect all date-level data.
Example code:
// Get user input values val employeeId = et_employee_id.text.toString().trim() val targetYear = et_year.text.toString().toIntOrNull() ?: return // Build Firebase reference to the employee's attendance records val attendanceRef = FirebaseDatabase.getInstance() .getReference("Attendance Records") .child(employeeId) // Listen for data changes attendanceRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val attendanceList = mutableListOf<AttendanceItem>() // Iterate through each month node under the employee for (monthSnapshot in snapshot.children) { val monthKey = monthSnapshot.key // e.g., "2024-10" for October 2024 // Check if the month belongs to the target year if (monthKey?.startsWith(targetYear.toString()) == true) { // Iterate through each date in the month for (daySnapshot in monthSnapshot.children) { val day = daySnapshot.key // e.g., "15" for the 15th val detail = daySnapshot.getValue(AttendanceDetail::class.java) // Create an AttendanceItem with default non-holiday status attendanceList.add(AttendanceItem("$monthKey-$day", detail, false)) } } } // After collecting attendance data, fetch holidays to mark relevant rows fetchAndMarkHolidays(targetYear, attendanceList) } override fun onCancelled(error: DatabaseError) { Toast.makeText(context, "Failed to load attendance data", Toast.LENGTH_SHORT).show() } })
Note: Create AttendanceDetail data class to map your attendance fields (like lateArrival, leaveEarly, etc.), and AttendanceItem as the RecyclerView display model (contains date string, detail, and a boolean for holiday status).
2. Mark holiday dates in the attendance list
To keep holidays flexible, add a Holidays node in Firebase with structure Holidays → 年份 → 日期列表 (e.g., Holidays/2024 stores values like "10-01", "10-02"). This lets you update holidays without app updates.
Code to fetch holidays and mark attendance items:
private fun fetchAndMarkHolidays(year: Int, attendanceList: MutableList<AttendanceItem>) { val holidayRef = FirebaseDatabase.getInstance() .getReference("Holidays") .child(year.toString()) holidayRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val holidayDates = mutableSetOf<String>() snapshot.children.forEach { holidayDates.add(it.value.toString()) // e.g., "10-01" } // Update holiday status for each attendance item attendanceList.forEach { item -> val dateSegment = item.date.split("-").takeLast(2).joinToString("-") item.isHoliday = holidayDates.contains(dateSegment) } // Refresh RecyclerView with updated data attendanceAdapter.submitList(attendanceList) } override fun onCancelled(error: DatabaseError) { Toast.makeText(context, "Failed to load holiday data", Toast.LENGTH_SHORT).show() } }) }
3. Display data with RecyclerView and color holiday rows
Create a custom AttendanceAdapter to render each attendance row, and adjust the row's appearance based on the isHoliday flag:
Example adapter code:
class AttendanceAdapter : ListAdapter<AttendanceItem, AttendanceAdapter.ViewHolder>(DiffCallback()) { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvDate: TextView = itemView.tv_attendance_date val tvDetail: TextView = itemView.tv_attendance_detail } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_attendance_row, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = getItem(position) holder.tvDate.text = item.date holder.tvDetail.text = item.detail?.let { "Status: ${it.status} | Hours: ${it.workHours}" } ?: "No record" // Color the row if it's a holiday if (item.isHoliday) { holder.itemView.setBackgroundColor(Color.parseColor("#FFF3E5F5")) // Light purple background holder.tvDate.setTextColor(Color.parseColor("#7B1FA2")) // Dark purple text } else { holder.itemView.setBackgroundColor(Color.WHITE) holder.tvDate.setTextColor(Color.BLACK) } } // DiffUtil to optimize RecyclerView updates class DiffCallback : DiffUtil.ItemCallback<AttendanceItem>() { override fun areItemsTheSame(oldItem: AttendanceItem, newItem: AttendanceItem): Boolean { return oldItem.date == newItem.date } override fun areContentsTheSame(oldItem: AttendanceItem, newItem: AttendanceItem): Boolean { return oldItem == newItem } } }
Extra Tips for Improvement
- Sort Dates: After collecting attendance data, sort the list by date to ensure chronological order.
- Offline Support: Enable Firebase's offline persistence so users can view cached records without internet.
- Loading States: Add a progress bar while fetching data to improve user experience.
内容的提问来源于stack exchange,提问作者Dpka

