Android自定义日历视图:实现打卡功能
Android自定义日历视图:实现打卡功能
概述
本文将指导您创建一个自定义的Android日历视图,并实现打卡功能。该视图允许用户直观地查看月份,选择日期,并标记已打卡的日期。
代码实现
1. CalendarView.java
该类继承自LinearLayout,负责日历视图的整体布局和逻辑。javaimport android.content.Context;import android.graphics.Color;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.AdapterView;import android.widget.GridView;import android.widget.LinearLayout;import android.widget.TextView;
import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Date;import java.util.HashSet;import java.util.List;import java.util.Locale;import java.util.Set;
public class CalendarView extends LinearLayout { private Context context; private GridView gridView; private TextView tvMonth; private CalendarAdapter adapter; private Calendar currentDate = Calendar.getInstance(); private SimpleDateFormat dateFormat = new SimpleDateFormat('MMMM yyyy', Locale.getDefault()); private Set
public CalendarView(Context context) { super(context); this.context = context; initialize(); }
public CalendarView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; initialize(); }
public CalendarView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; initialize(); }
private void initialize() { LayoutInflater inflater = LayoutInflater.from(context); inflater.inflate(R.layout.calendar_view, this);
gridView = findViewById(R.id.gridview); tvMonth = findViewById(R.id.tv_month);
findViewById(R.id.btn_prev).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { currentDate.add(Calendar.MONTH, -1); updateCalendar(); } });
findViewById(R.id.btn_next).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { currentDate.add(Calendar.MONTH, 1); updateCalendar(); } });
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (onDateClickListener != null) { Date date = (Date) parent.getItemAtPosition(position); onDateClickListener.onDateClick(date); } } });
updateCalendar(); }
public void setOnDateClickListener(OnDateClickListener listener) { this.onDateClickListener = listener; }
public void markDate(Date date) { markedDates.add(date); adapter.notifyDataSetChanged(); }
private void updateCalendar() { List<Date> dates = getDates(); adapter = new CalendarAdapter(context, dates, currentDate, markedDates); gridView.setAdapter(adapter); tvMonth.setText(dateFormat.format(currentDate.getTime())); }
private List<Date> getDates() { List<Date> dates = new ArrayList<>(); Calendar calendar = (Calendar) currentDate.clone(); calendar.set(Calendar.DAY_OF_MONTH, 1); int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; calendar.add(Calendar.DAY_OF_MONTH, -firstDayOfWeek);
while (dates.size() < 42) { dates.add(calendar.getTime()); calendar.add(Calendar.DAY_OF_MONTH, 1); }
return dates; }
public interface OnDateClickListener { void onDateClick(Date date); }}
2. calendar_view.xml
该布局文件定义了CalendarView的结构,包括月份显示、上/下一月按钮和日期网格。xml
<LinearLayout android:layout_width='match_parent' android:layout_height='wrap_content' android:orientation='horizontal'>
<Button android:id='@+id/btn_prev' android:layout_width='wrap_content' android:layout_height='wrap_content' android:text='Prev' />
<TextView android:id='@+id/tv_month' android:layout_width='0dp' android:layout_height='wrap_content' android:layout_weight='1' android:gravity='center' android:textSize='20sp' />
<Button android:id='@+id/btn_next' android:layout_width='wrap_content' android:layout_height='wrap_content' android:text='Next' />
</LinearLayout>
<GridView android:id='@+id/gridview' android:layout_width='match_parent' android:layout_height='wrap_content' android:numColumns='7' android:verticalSpacing='1dp' android:horizontalSpacing='1dp' android:stretchMode='columnWidth' />
3. CalendarAdapter.java
该适配器负责填充日期网格,并根据日期状态设置不同的样式。javaimport android.content.Context;import android.graphics.Color;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;
import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.Set;
public class CalendarAdapter extends BaseAdapter { private Context context; private List
public CalendarAdapter(Context context, List<Date> dates, Calendar currentDate, Set<Date> markedDates) { this.context = context; this.dates = dates; this.currentDate = currentDate; this.markedDates = markedDates; }
@Override public int getCount() { return dates.size(); }
@Override public Object getItem(int position) { return dates.get(position); }
@Override public long getItemId(int position) { return position; }
@Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView;
if (view == null) { LayoutInflater inflater = LayoutInflater.from(context); view = inflater.inflate(R.layout.calendar_item, parent, false); }
TextView tvDate = view.findViewById(R.id.tv_date); Date date = dates.get(position); tvDate.setText(dateFormat.format(date));
if (date.getMonth() != currentDate.getTime().getMonth()) { tvDate.setTextColor(Color.GRAY); } else { tvDate.setTextColor(Color.BLACK); }
if (markedDates.contains(date)) { tvDate.setBackgroundResource(R.drawable.circle_background); // 设置已打卡日期的背景样式 } else { tvDate.setBackground(null); // 清除未打卡日期的背景样式 }
return view; }}
4. calendar_item.xml
该布局文件定义了日期网格中每个日期项的样式。xml
使用方法
-
将上述代码文件添加到您的Android项目中。2. 在您的主布局文件中添加
CalendarView控件:xml<com.example.myapplication.CalendarView android:id='@+id/calendar_view' android:layout_width='match_parent' android:layout_height='wrap_content' /> -
在您的主活动中找到
CalendarView控件并设置监听器:javaCalendarView calendarView = findViewById(R.id.calendar_view);calendarView.setOnDateClickListener(new CalendarView.OnDateClickListener() { @Override public void onDateClick(Date date) { handleDateClick(date); }}); -
在
handleDateClick()方法中处理日期点击事件:javaprivate void handleDateClick(Date date) { // 更新UI SimpleDateFormat dateFormat = new SimpleDateFormat('yyyy-MM-dd', Locale.getDefault()); String selectedDate = dateFormat.format(date); textView.setText(selectedDate);// 保存选中的日期 // ...}
-
调用
markDate()方法来标记已打卡的日期:javaCalendarView calendarView = findViewById(R.id.calendar_view);calendarView.markDate(new Date()); // 标记今天为已打卡
总结
通过以上步骤,您可以轻松地创建一个自定义的Android日历视图,并实现打卡功能。您可以根据需要修改代码和样式,以满足您的特定需求。
原文地址: https://www.cveoy.top/t/topic/beqT 著作权归作者所有。请勿转载和采集!