Android自定义日历控件,实现打卡功能

本文将介绍如何创建一个自定义的Android日历控件,并实现打卡功能。该控件允许用户查看日历并标记特定日期,例如打卡记录。

1. 创建布局文件

首先,我们需要创建三个布局文件:

calendar_view.xml:日历控件的主布局文件。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' />

calendar_item.xml:日历网格中每个日期项的布局文件。xml

circle_background.xml:已打卡日期的背景样式,可根据需求自定义。xml

2. 创建日历控件类

接下来,我们需要创建一个名为 CalendarView 的自定义 View 类,该类继承自 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 markedDates = new HashSet<>(); private OnDateClickListener onDateClickListener;

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);    }}

3. 创建日历适配器

为了在 GridView 中显示日期,我们需要创建一个名为 CalendarAdapter 的适配器类,该类继承自 BaseAdapter。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 dates; private Calendar currentDate; private SimpleDateFormat dateFormat = new SimpleDateFormat('dd', Locale.getDefault()); private Set markedDates;

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. 在主活动中使用日历控件

最后,在主活动的布局文件中添加 CalendarView 控件,并在主活动的 Java 代码中使用它。

activity_main.xmlxml<com.example.myapplication.CalendarView android:id='@+id/calendar_view' android:layout_width='match_parent' android:layout_height='wrap_content' />

MainActivity.javajavaimport android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;

public class MainActivity extends AppCompatActivity {

@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);

    CalendarView calendarView = findViewById(R.id.calendar_view);        calendarView.setOnDateClickListener(new CalendarView.OnDateClickListener() {            @Override            public void onDateClick(Date date) {                handleDateClick(date);            }        });

    calendarView.markDate(new Date()); // 标记今天为已打卡    }

private void handleDateClick(Date date) {        // 处理日期点击事件,例如更新UI、保存选中的日期等        SimpleDateFormat dateFormat = new SimpleDateFormat('yyyy-MM-dd', Locale.getDefault());        String selectedDate = dateFormat.format(date);        // ...    }}

总结

通过以上步骤,我们创建了一个自定义的 Android 日历控件,并实现了打卡功能。你可以根据自己的需要修改代码,例如自定义日期样式、添加事件监听器等。

Android自定义日历控件,实现打卡功能

原文地址: http://www.cveoy.top/t/topic/behZ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录