Android开发之打卡功能

  • 一、效果图
  • 二、项目结构
  • 三、布局文件(activity_main)
  • 四、drawable中新建btn_sign_bg_selector.xml
  • 五、drawable中新建btn_sign_bg_enable.xml
  • 六、drawable中新建btn_sign_bg_unable.xml
  • 七、drawable中新建bg_sign_today.xml
  • 八、res包下新建anim包
    • 1.anim中新建push_left_in.xml
    • 2.anim中新建push_left_out.xml
    • 3.anim中新建push_right_in.xml
    • 4.anim中新建push_right_out.xml
  • 九、drawable中图片
    • 1.calendar_date_focused.png
    • 2.calendar_bg_tag.png
    • 3.calendar_day_bg.9.png
  • 十、res包下的values包下新建dimens.xml
  • 十一、主java文件(MainActivity)
  • 十二、SignCalendar
  • 十三、资源下载地址:[Android开发之打卡功能](https://download.csdn.net/download/qq_61963074/86434936)

此篇实现每日打卡功能,有兴趣的小伙伴可以试试。
老规矩,直接上代码!

一、效果图

二、项目结构

三、布局文件(activity_main)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffffff"tools:context=".MainActivity" ><LinearLayoutandroid:id="@+id/ll_popup"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#ffeeeeee"android:orientation="vertical" ><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="60dp"android:layout_marginTop="10dp"android:background="#586771" ><TextViewandroid:id="@+id/popupwindow_calendar_month"android:layout_width="match_parent"android:layout_height="60dp"android:background="#586771"android:gravity="center"android:textColor="#aa564b4b"android:textSize="18sp" /></RelativeLayout><com.example.SignCalendarandroid:id="@+id/popupwindow_calendar"android:layout_width="match_parent"android:layout_height="320dp"android:clickable="false" ></com.example.SignCalendar><Buttonandroid:id="@+id/btn_signIn"android:layout_width="match_parent"android:layout_height="45dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="20dp"android:background="@drawable/btn_sign_bg_selector"android:text="打卡"android:textColor="@android:color/white"android:textSize="16sp" /></LinearLayout></RelativeLayout>

四、drawable中新建btn_sign_bg_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" ><item android:drawable="@drawable/btn_sign_bg_enable" android:state_enabled="true"/><item  android:drawable="@drawable/btn_sign_bg_unable"/>
</selector>

五、drawable中新建btn_sign_bg_enable.xml

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

六、drawable中新建btn_sign_bg_unable.xml

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

七、drawable中新建bg_sign_today.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><stroke android:width="1px" android:color="#FF4F14"/><solid android:color="@android:color/transparent"/></shape>

八、res包下新建anim包

1.anim中新建push_left_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromXDelta="100%p"android:toXDelta="0"android:duration="400"/><alphaandroid:fromAlpha="0.0"android:toAlpha="1.0"android:duration="400" />
</set>

2.anim中新建push_left_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromXDelta="0"android:toXDelta="-100%p"android:duration="400"/><alphaandroid:fromAlpha="1.0"android:toAlpha="0.0"android:duration="400" />
</set>

3.anim中新建push_right_in.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromXDelta="-100%p"android:toXDelta="0"android:duration="400"/><alphaandroid:fromAlpha="0.0"android:toAlpha="1.0"android:duration="400" />
</set>

4.anim中新建push_right_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromXDelta="0"android:toXDelta="100%p"android:duration="400"/><alphaandroid:fromAlpha="1.0"android:toAlpha="1.0"android:duration="400" />
</set>

九、drawable中图片

1.calendar_date_focused.png

2.calendar_bg_tag.png

3.calendar_day_bg.9.png

十、res包下的values包下新建dimens.xml

<resources><!-- Default screen margins, per the Android Design guidelines. --><dimen name="activity_horizontal_margin">16dp</dimen><dimen name="activity_vertical_margin">16dp</dimen><dimen name="historyscore_tb">10dp</dimen>
</resources>

十一、主java文件(MainActivity)

package com.example;import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;import com.example.R;
import com.example.SignCalendar.OnCalendarDateChangedListener;public class MainActivity extends Activity {private String date = null;// 设置默认选中的日期  格式为 “2014-04-05” 标准DATE格式private TextView popupwindow_calendar_month;private SignCalendar calendar;private Button btn_signIn;private List<String> list = new ArrayList<String>(); //设置标记列表protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);popupwindow_calendar_month = (TextView) findViewById(R.id.popupwindow_calendar_month);btn_signIn = (Button) findViewById(R.id.btn_signIn);calendar = (SignCalendar) findViewById(R.id.popupwindow_calendar);popupwindow_calendar_month.setText(calendar.getCalendarYear() + "年"+ calendar.getCalendarMonth() + "月");if (null != date) {int years = Integer.parseInt(date.substring(0,date.indexOf("-")));int month = Integer.parseInt(date.substring(date.indexOf("-") + 1, date.lastIndexOf("-")));popupwindow_calendar_month.setText(years + "年" + month + "月");calendar.showCalendar(years, month);calendar.setCalendarDayBgColor(date,R.drawable.calendar_date_focused);}list.add("2015-11-10");list.add("2015-11-02");calendar.addMarks(list, 0);btn_signIn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Date today= calendar.getThisday();calendar.addMark(today, 0);HashMap<String, Integer> bg = new HashMap<String, Integer>();calendar.setCalendarDayBgColor(today, R.drawable.bg_sign_today);btn_signIn.setText("今日已签,明日继续");btn_signIn.setEnabled(false);}});//监听所选中的日期
//      calendar.setOnCalendarClickListener(new OnCalendarClickListener() {//
//          public void onCalendarClick(int row, int col, String dateFormat) {//              int month = Integer.parseInt(dateFormat.substring(
//                      dateFormat.indexOf("-") + 1,
//                      dateFormat.lastIndexOf("-")));
//
//              if (calendar.getCalendarMonth() - month == 1//跨年跳转
//                      || calendar.getCalendarMonth() - month == -11) {//                  calendar.lastMonth();
//
//              } else if (month - calendar.getCalendarMonth() == 1 //跨年跳转
//                      || month - calendar.getCalendarMonth() == -11) {//                  calendar.nextMonth();
//
//              } else {//                  list.add(dateFormat);
//                  calendar.addMarks(list, 0);
//                  calendar.removeAllBgColor();
//                  calendar.setCalendarDayBgColor(dateFormat,
//                          R.drawable.calendar_date_focused);
//                  date = dateFormat;//最后返回给全局 date
//              }
//          }
//      });//监听当前月份calendar.setOnCalendarDateChangedListener(new OnCalendarDateChangedListener() {public void onCalendarDateChanged(int year, int month) {popupwindow_calendar_month.setText(year + "年" + month + "月");}});}}

十二、SignCalendar

package com.example;import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.ViewFlipper;/***** @author sxc 类说明:*/
@SuppressWarnings("deprecation")
public class SignCalendar extends ViewFlipper implementsandroid.view.GestureDetector.OnGestureListener {public static final int COLOR_BG_WEEK_TITLE = Color.parseColor("#ff999999"); // 星期标题背景颜色public static final int COLOR_TX_WEEK_TITLE = Color.parseColor("#ffcc3333"); // 星期标题文字颜色public static final int BEFORE_TODAY_BACKGROUND = Color.parseColor("#FFE4E4E4"); // 星期标题文字颜色// public static final int COLOR_TX_THIS_MONTH_DAY = Color.parseColor("#aa564b4b"); // 当前月日历数字颜色public static final int COLOR_TX_THIS_MONTH_DAY = Color.parseColor("#000000"); // 当前月日历数字颜色public static final int COLOR_TX_OTHER_MONTH_DAY = Color.parseColor("#ff999999"); // 其他月日历数字颜色public static final int COLOR_TX_THIS_DAY = Color.parseColor("#ff008000"); // 当天日历数字颜色public static final int COLOR_BG_THIS_DAY = Color.parseColor("#ffcccccc"); // 当天日历背景颜色public static final int COLOR_BG_CALENDAR = Color.parseColor("#ffeeeeee"); // 日历背景色private GestureDetector gd; // 手势监听器private Animation push_left_in; // 动画-左进private Animation push_left_out; // 动画-左出private Animation push_right_in; // 动画-右进private Animation push_right_out; // 动画-右出private int ROWS_TOTAL = 6; // 日历的行数private int COLS_TOTAL = 7; // 日历的列数private String[][] dates = new String[6][7]; // 当前日历日期private float tb;private OnCalendarClickListener onCalendarClickListener; // 日历翻页回调private OnCalendarDateChangedListener onCalendarDateChangedListener; // 日历点击回调private String[] weekday = new String[] {"日", "一", "二", "三", "四", "五", "六"}; // 星期标题private int calendarYear; // 日历年份private int calendarMonth; // 日历月份private Date thisday = new Date(); // 今天private Date calendarday; // 日历这个月第一天(1号)private LinearLayout firstCalendar; // 第一个日历private LinearLayout secondCalendar; // 第二个日历private LinearLayout currentCalendar; // 当前显示的日历private Map<String, Integer> marksMap = new HashMap<String, Integer>(); // 储存某个日子被标注(Integer// 为bitmap// res// id)private Map<String, Integer> dayBgColorMap = new HashMap<String, Integer>(); // 储存某个日子的背景色public SignCalendar(Context context, AttributeSet attrs) {super(context, attrs);init();}public SignCalendar(Context context) {super(context);init();}private void init() {setBackgroundColor(COLOR_BG_CALENDAR);// 实例化收拾监听器gd = new GestureDetector(this.getContext(), this);// 初始化日历翻动动画push_left_in = AnimationUtils.loadAnimation(getContext(), R.anim.push_left_in);push_left_out = AnimationUtils.loadAnimation(getContext(), R.anim.push_left_out);push_right_in = AnimationUtils.loadAnimation(getContext(), R.anim.push_right_in);push_right_out = AnimationUtils.loadAnimation(getContext(), R.anim.push_right_out);// 初始化第一个日历firstCalendar = new LinearLayout(getContext());firstCalendar.setOrientation(LinearLayout.VERTICAL);firstCalendar.setLayoutParams(new LinearLayout.LayoutParams(-1, -1));// 初始化第二个日历secondCalendar = new LinearLayout(getContext());secondCalendar.setOrientation(LinearLayout.VERTICAL);secondCalendar.setLayoutParams(new LinearLayout.LayoutParams(-1, -1));// 设置默认日历为第一个日历currentCalendar = firstCalendar;// 加入ViewFlipperaddView(firstCalendar);addView(secondCalendar);// 绘制线条框架drawFrame(firstCalendar);drawFrame(secondCalendar);// 设置日历上的日子(1号)calendarYear = thisday.getYear() + 1900;calendarMonth = thisday.getMonth();calendarday = new Date(calendarYear - 1900, calendarMonth, 1);// 填充展示日历setCalendarDate();}private void drawFrame(LinearLayout oneCalendar) {// 添加周末线性布局LinearLayout title = new LinearLayout(getContext());title.setBackgroundColor(COLOR_BG_WEEK_TITLE);title.setOrientation(LinearLayout.HORIZONTAL);LinearLayout.LayoutParams layout =new LinearLayout.LayoutParams(MarginLayoutParams.MATCH_PARENT,MarginLayoutParams.WRAP_CONTENT, 0.5f);Resources res = getResources();tb = res.getDimension(R.dimen.historyscore_tb);// layout.setMargins(0, 0, 0, (int) (tb * 1.2));title.setLayoutParams(layout);oneCalendar.addView(title);// 添加周末TextViewfor (int i = 0; i < COLS_TOTAL; i++) {TextView view = new TextView(getContext());view.setGravity(Gravity.CENTER);view.setPadding(0, 10, 0, 10);view.setText(weekday[i]);view.setTextColor(Color.WHITE);view.setLayoutParams(new LinearLayout.LayoutParams(0, -1, 1));title.addView(view);}// 添加日期布局LinearLayout content = new LinearLayout(getContext());content.setOrientation(LinearLayout.VERTICAL);content.setLayoutParams(new LinearLayout.LayoutParams(-1, 0, 7f));oneCalendar.addView(content);// 添加日期TextViewfor (int i = 0; i < ROWS_TOTAL; i++) {LinearLayout row = new LinearLayout(getContext());row.setOrientation(LinearLayout.HORIZONTAL);row.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1));content.addView(row);// 绘制日历上的列for (int j = 0; j < COLS_TOTAL; j++) {RelativeLayout col = new RelativeLayout(getContext());col.setLayoutParams(new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1));col.setBackgroundResource(R.drawable.calendar_day_bg);// col.setBackgroundResource(R.drawable.sign_dialog_day_bg);col.setClickable(false);row.addView(col);// 给每一个日子加上监听col.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {ViewGroup parent = (ViewGroup) v.getParent();int row = 0, col = 0;// 获取列坐标for (int i = 0; i < parent.getChildCount(); i++) {if (v.equals(parent.getChildAt(i))) {col = i;break;}}// 获取行坐标ViewGroup pparent = (ViewGroup) parent.getParent();for (int i = 0; i < pparent.getChildCount(); i++) {if (parent.equals(pparent.getChildAt(i))) {row = i;break;}}if (onCalendarClickListener != null) {onCalendarClickListener.onCalendarClick(row, col, dates[row][col]);}}});}}}/*** 填充日历(包含日期、标记、背景等)*/private void setCalendarDate() {// 根据日历的日子获取这一天是星期几int weekday = calendarday.getDay();// 每个月第一天int firstDay = 1;// 每个月中间号,根据循环会自动++int day = firstDay;// 每个月的最后一天int lastDay = getDateNum(calendarday.getYear(), calendarday.getMonth());// 下个月第一天int nextMonthDay = 1;int lastMonthDay = 1;// 填充每一个空格for (int i = 0; i < ROWS_TOTAL; i++) {for (int j = 0; j < COLS_TOTAL; j++) {// 这个月第一天不是礼拜天,则需要绘制上个月的剩余几天if (i == 0 && j == 0 && weekday != 0) {int year = 0;int month = 0;int lastMonthDays = 0;// 如果这个月是1月,上一个月就是去年的12月if (calendarday.getMonth() == 0) {year = calendarday.getYear() - 1;month = Calendar.DECEMBER;} else {year = calendarday.getYear();month = calendarday.getMonth() - 1;}// 上个月的最后一天是几号lastMonthDays = getDateNum(year, month);// 第一个格子展示的是几号int firstShowDay = lastMonthDays - weekday + 1;// 上月for (int k = 0; k < weekday; k++) {lastMonthDay = firstShowDay + k;RelativeLayout group = getDateView(0, k);group.setGravity(Gravity.CENTER);TextView view = null;if (group.getChildCount() > 0) {view = (TextView) group.getChildAt(0);} else {LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1);view = new TextView(getContext());view.setLayoutParams(params);view.setGravity(Gravity.CENTER);group.addView(view);}view.setText(Integer.toString(lastMonthDay));view.setTextColor(COLOR_TX_OTHER_MONTH_DAY);dates[0][k] = format(new Date(year, month, lastMonthDay));// 设置日期背景色if (dayBgColorMap.get(dates[0][k]) != null) {view.setBackgroundResource(dayBgColorMap.get(dates[0][k]));} else {view.setBackgroundColor(Color.TRANSPARENT);}// 设置标记setMarker(group, 0, k);}j = weekday - 1;// 这个月第一天是礼拜天,不用绘制上个月的日期,直接绘制这个月的日期} else {RelativeLayout group = getDateView(i, j);group.setGravity(Gravity.CENTER);TextView view = null;if (group.getChildCount() > 0) {view = (TextView) group.getChildAt(0);} else {LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1);view = new TextView(getContext());view.setLayoutParams(params);view.setGravity(Gravity.CENTER);group.addView(view);}// 本月if (day <= lastDay) {dates[i][j] = format(new Date(calendarday.getYear(), calendarday.getMonth(), day));view.setText(Integer.toString(day));// 当天if (thisday.getDate() == day && thisday.getMonth() == calendarday.getMonth()&& thisday.getYear() == calendarday.getYear()) {// view.setText("今天");view.setTextColor(COLOR_TX_THIS_MONTH_DAY);// view.setBackgroundResource(R.drawable.bg_sign_today);} else if (thisday.getMonth() == calendarday.getMonth()) {view.setTextColor(COLOR_TX_THIS_MONTH_DAY);} else {view.setTextColor(COLOR_TX_OTHER_MONTH_DAY);}// 上面首先设置了一下默认的"当天"背景色,当有特殊需求时,才给当日填充背景色// 设置日期背景色if (dayBgColorMap.get(dates[i][j]) != null) {// view.setTextColor(Color.WHITE);view.setBackgroundResource(dayBgColorMap.get(dates[i][j]));}// 设置标记setMarker(group, i, j);day++;// 下个月} else {if (calendarday.getMonth() == Calendar.DECEMBER) {dates[i][j] =format(new Date(calendarday.getYear() + 1, Calendar.JANUARY, nextMonthDay));} else {dates[i][j] =format(new Date(calendarday.getYear(), calendarday.getMonth() + 1, nextMonthDay));}view.setText(Integer.toString(nextMonthDay));view.setTextColor(COLOR_TX_OTHER_MONTH_DAY);// 设置日期背景色if (dayBgColorMap.get(dates[i][j]) != null) {// view.setBackgroundResource(dayBgColorMap// .get(dates[i][j]));} else {view.setBackgroundColor(Color.TRANSPARENT);}// 设置标记setMarker(group, i, j);nextMonthDay++;}}}}}/*** onClick接口回调*/public interface OnCalendarClickListener {void onCalendarClick(int row, int col, String dateFormat);}/*** ondateChange接口回调*/public interface OnCalendarDateChangedListener {void onCalendarDateChanged(int year, int month);}/*** 根据具体的某年某月,展示一个日历** @param year* @param month*/public void showCalendar(int year, int month) {calendarYear = year;calendarMonth = month - 1;calendarday = new Date(calendarYear - 1900, calendarMonth, 1);setCalendarDate();}/*** 根据当前月,展示一个日历**/public void showCalendar() {Date now = new Date();calendarYear = now.getYear() + 1900;calendarMonth = now.getMonth();calendarday = new Date(calendarYear - 1900, calendarMonth, 1);setCalendarDate();}/*** 下一月日历*/public synchronized void nextMonth() {// 改变日历上下顺序if (currentCalendar == firstCalendar) {currentCalendar = secondCalendar;} else {currentCalendar = firstCalendar;}// 设置动画setInAnimation(push_left_in);setOutAnimation(push_left_out);// 改变日历日期if (calendarMonth == Calendar.DECEMBER) {calendarYear++;calendarMonth = Calendar.JANUARY;} else {calendarMonth++;}calendarday = new Date(calendarYear - 1900, calendarMonth, 1);// 填充日历setCalendarDate();// 下翻到下一月showNext();// 回调if (onCalendarDateChangedListener != null) {onCalendarDateChangedListener.onCalendarDateChanged(calendarYear, calendarMonth + 1);}}/*** 上一月日历*/public synchronized void lastMonth() {if (currentCalendar == firstCalendar) {currentCalendar = secondCalendar;} else {currentCalendar = firstCalendar;}setInAnimation(push_right_in);setOutAnimation(push_right_out);if (calendarMonth == Calendar.JANUARY) {calendarYear--;calendarMonth = Calendar.DECEMBER;} else {calendarMonth--;}calendarday = new Date(calendarYear - 1900, calendarMonth, 1);setCalendarDate();showPrevious();if (onCalendarDateChangedListener != null) {onCalendarDateChangedListener.onCalendarDateChanged(calendarYear, calendarMonth + 1);}}/*** 获取日历当前年份*/public int getCalendarYear() {return calendarday.getYear() + 1900;}/*** 获取日历当前月份*/public int getCalendarMonth() {return calendarday.getMonth() + 1;}/*** 在日历上做一个标记** @param date 日期* @param id bitmap res id*/public void addMark(Date date, int id) {addMark(format(date), id);}/*** 在日历上做一个标记** @param date 日期* @param id bitmap res id*/public void addMark(String date, int id) {marksMap.put(date, id);setCalendarDate();}/*** 在日历上做一组标记** @param date 日期* @param id bitmap res id*/public void addMarks(Date[] date, int id) {for (int i = 0; i < date.length; i++) {marksMap.put(format(date[i]), id);}setCalendarDate();}/*** 在日历上做一组标记** @param date 日期* @param id bitmap res id*/public void addMarks(List<String> date, int id) {for (int i = 0; i < date.size(); i++) {marksMap.put(date.get(i), id);}setCalendarDate();}/*** 移除日历上的标记*/public void removeMark(Date date) {removeMark(format(date));}/*** 移除日历上的标记*/public void removeMark(String date) {marksMap.remove(date);setCalendarDate();}/*** 移除日历上的所有标记*/public void removeAllMarks() {marksMap.clear();setCalendarDate();}/*** 设置日历具体某个日期的背景色** @param date* @param color*/public void setCalendarDayBgColor(Date date, int color) {setCalendarDayBgColor(format(date), color);}/*** 设置日历具体某个日期的背景色** @param date* @param color*/public void setCalendarDayBgColor(String date, int color) {dayBgColorMap.put(date, color);setCalendarDate();}/*** 设置日历一组日期的背景色** @param date* @param color*/public void setCalendarDaysBgColor(List<String> date, int color) {for (int i = 0; i < date.size(); i++) {dayBgColorMap.put(date.get(i), color);}setCalendarDate();}/*** 设置日历一组日期的背景色** @param date* @param color*/public void setCalendarDayBgColor(String[] date, int color) {for (int i = 0; i < date.length; i++) {dayBgColorMap.put(date[i], color);}setCalendarDate();}/*** 移除日历具体某个日期的背景色*/public void removeCalendarDayBgColor(Date date) {removeCalendarDayBgColor(format(date));}/*** 移除日历具体某个日期的背景色**/public void removeCalendarDayBgColor(String date) {dayBgColorMap.remove(date);setCalendarDate();}/*** 移除日历具体某个日期的背景色**/public void removeAllBgColor() {dayBgColorMap.clear();setCalendarDate();}/*** 根据行列号获得包装每一个日子的LinearLayout** @return*/public String getDate(int row, int col) {return dates[row][col];}/*** 某天是否被标记了** @return*/public boolean hasMarked(String date) {return marksMap.get(date) == null ? false : true;}/*** 清除所有标记以及背景*/public void clearAll() {marksMap.clear();dayBgColorMap.clear();}/************************************************* private methods***********************************************/// 设置标记private void setMarker(RelativeLayout group, int i, int j) {int childCount = group.getChildCount();if (marksMap.get(dates[i][j]) != null) {if (childCount < 2) {RelativeLayout.LayoutParams params =new RelativeLayout.LayoutParams((int) (tb * 0.7), (int) (tb * 0.7));params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);params.setMargins(0, 0, 1, 1);ImageView markView = new ImageView(getContext());markView.setImageResource(marksMap.get(dates[i][j]));markView.setLayoutParams(params);markView.setBackgroundResource(R.drawable.calendar_bg_tag);group.addView(markView);}} else {if (childCount > 1) {group.removeView(group.getChildAt(1));}}}/*** 计算某年某月有多少天** @param year* @param month* @return*/private int getDateNum(int year, int month) {Calendar time = Calendar.getInstance();time.clear();time.set(Calendar.YEAR, year + 1900);time.set(Calendar.MONTH, month);return time.getActualMaximum(Calendar.DAY_OF_MONTH);}/*** 根据行列号获得包装每一个日子的LinearLayout** @param row* @param col* @return*/private RelativeLayout getDateView(int row, int col) {return (RelativeLayout) ((LinearLayout) ((LinearLayout) currentCalendar.getChildAt(1)).getChildAt(row)).getChildAt(col);}/*** 将Date转化成字符串->2013-3-3*/private String format(Date d) {return addZero(d.getYear() + 1900, 4) + "-" + addZero(d.getMonth() + 1, 2) + "-"+ addZero(d.getDate(), 2);}// 2或4private static String addZero(int i, int count) {if (count == 2) {if (i < 10) {return "0" + i;}} else if (count == 4) {if (i < 10) {return "000" + i;} else if (i < 100 && i > 10) {return "00" + i;} else if (i < 1000 && i > 100) {return "0" + i;}}return "" + i;}/************************************************* Override methods***********************************************/public boolean dispatchTouchEvent(MotionEvent ev) {if (gd != null) {if (gd.onTouchEvent(ev))return true;}return super.dispatchTouchEvent(ev);}public boolean onTouchEvent(MotionEvent event) {return this.gd.onTouchEvent(event);}public boolean onDown(MotionEvent e) {return false;}public void onShowPress(MotionEvent e) {}public boolean onSingleTapUp(MotionEvent e) {return false;}public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return false;}public void onLongPress(MotionEvent e) {}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {// 向左/上滑动if (e1.getX() - e2.getX() > 20) {nextMonth();}// 向右/下滑动else if (e1.getX() - e2.getX() < -20) {lastMonth();}return false;}/************************************************* get/set methods***********************************************/public OnCalendarClickListener getOnCalendarClickListener() {return onCalendarClickListener;}public void setOnCalendarClickListener(OnCalendarClickListener onCalendarClickListener) {this.onCalendarClickListener = onCalendarClickListener;}public OnCalendarDateChangedListener getOnCalendarDateChangedListener() {return onCalendarDateChangedListener;}public void setOnCalendarDateChangedListener(OnCalendarDateChangedListener onCalendarDateChangedListener) {this.onCalendarDateChangedListener = onCalendarDateChangedListener;}public Date getThisday() {return thisday;}public void setThisday(Date thisday) {this.thisday = thisday;}public Map<String, Integer> getDayBgColorMap() {return dayBgColorMap;}public void setDayBgColorMap(Map<String, Integer> dayBgColorMap) {this.dayBgColorMap = dayBgColorMap;}
}

十三、资源下载地址:Android开发之打卡功能

好了,一个简单的打卡器就做成了,还有不懂的欢迎交流

Android开发之打卡功能相关推荐

  1. Android开发日志打卡APP(一)

    Android开发日志打卡APP(一) 文章目录 Android开发日志打卡APP(一) 简介 界面展示 内容总结 1.控件 2.布局 3.技术 开发过程 准备工作 启动页面 底部导航栏 简介 ​ 初 ...

  2. Android开发日志打卡APP(二)

    Android开发日志打卡APP(二) 文章目录 Android开发日志打卡APP(二) 前言 开发过程 一.背景和标题 二.日志图标 三.日志弹框 前言 在之前的文章中,准备工作已经完成,现在我们将 ...

  3. android微信支付都需要什么意思,Android开发微信APP支付功能的要点小结

    基本概念 包名值得是你APP的包,在创建工程时候设置的,需要在微信支付平台上面设置. 签名指的是你生成APK时候所用的签名文件的md5,去掉:全部小写,需要在微信支付平台上面设置. 调试阶段,签名文件 ...

  4. Android开发之评论回复功能

    Android开发之评论回复功能 一:效果图 二:具体代码 1.首先是布局文件(activity_main) 2.第二个布局文件(comment_item) 3.第三个布局文件(reply_item) ...

  5. Android开发最近新闻和功能都在这里了

    在Android开发领域,12月是相对安静的月份,Android Developers博客上的帖子数量比往常少很多.根据道客优从外媒看的说法是许多其他网站在假期期间会休息,开发人员也需要休息! 尽管如 ...

  6. 浅谈Android开发中的NFC功能

    目录 1."NFC"的自我描述 1.1 NFC功能的基本概念 1.2 NFC功能的背景.特性及发展趋势 2.NFC的基础知识.基本原理 2.1 NFC的工作模式 2.2 实现NFC ...

  7. android实现存储,Android开发实现文件存储功能

    本文实例为大家分享了Android开发实现文件存储的具体代码,供大家参考,具体内容如下 这个程序只有一个Activity, Activity中只有一个Edittext.实现的功能是在Activity销 ...

  8. Android开发技巧——Camera拍照功能

    本篇是我对开发项目的拍照功能过程中,对Camera拍照使用的总结.由于camera2是在api level 21(5.0.1)才引入的,而Camera到6.0仍可使用,所以暂未考虑camera2. 文 ...

  9. android+解锁风格,Android开发实现图案解锁功能

    释放双眼,带上耳机,听听看~! 学习目的 学习新的Android开发相关知识,并通过代码实现图案解锁功能 相关技术.及其使用 注意:在界面上添加控件都需要给控件指定其在界面上所处的位置 及 X ,Y ...

  10. Android开发扫一扫功能,Android使用ZXing实现扫码功能

    最近正在开发app,基本功能已开发完成,剩下扫码识别功能.之前上级已经写了一版,不是很好用,让我自己好好琢磨一下.针对这种功能需求,一般就先google,看有没有现成的代码可用,不出所料,果然有很多. ...

最新文章

  1. java中Class.forName与new
  2. 普诺飞思获创新工场新一轮投资,加速神经拟态视觉传感技术商业化
  3. opencv orb
  4. Spring 事务机制详解
  5. 使用 CodeIgniter 框架快速开发 PHP 应用(五)
  6. jstl自定义标签接口介绍
  7. HTTP 错误 500.21 - Internal Server Error 处理程序“PageHandlerFactory-ISAPI-4.0_32bit”在其模块...
  8. ci发什么音标_48个国际音标发音舌位图
  9. java 线程执行结束_Java_如何等待子线程执行结束
  10. 服务器配置列表在哪个文件夹,FolderMagic
  11. 在内存流中对象的二进制序列化的问题
  12. 优化器——梯度下降优化算法综述
  13. ORCLE INNODB 博客与 innodb_lru_scan_depth
  14. Atitit uuid 的概念与实现与最佳实践总结 目录 1. 概念与组成 1 1.1. 在空间(Space)与时间(Time)上的唯一性 1 1.2. UUID 1 1.3. 组成 2 1.3.1
  15. C# 中用 PadLeft、PadRight 补足位数
  16. CopyU!v2 已经收录到腾讯软件管家!
  17. jsp实现登录验证码
  18. 需要TrustedInstaller权限才可以删除解决办法
  19. 小程序毕设作品之微信评选投票小程序毕业设计(4)开题报告
  20. 推荐几款好用的云笔记软件

热门文章

  1. Lync Server 2013 标准版的DNS和端口要求
  2. 大数据到底怎么学:数据科学概论与大数据学习误区
  3. 发个贴,舒缓下自己焦虑的心情
  4. LeeCode 108 递归
  5. tp5微信公众号开发(1) 申请公众号配置token验证
  6. Windows中的键盘快捷方式大全
  7. input框只能输入非负数
  8. 嵌入式软件测试环境搭建,基于DOORS的嵌入式软件测试环境需求管理
  9. 电脑账户服务器未能登录拒绝访问,win7系统开机提示服务未能登入拒绝访问的解决方法...
  10. 计算机语音识别引擎,基于微软语音引擎的语音识别技术的研究