Android可签到日历控件的实现方法

最近在公司的功能需求中,需要实现可以签到的日历,签到后在签到过的日期做标志。本功能参考了网上一些大神的日历控件,在此基础上进行修改,已满足本公司的需求,现已完成,记录一下。

布局文件:

<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="@color/white"
 android:orientation="vertical">

 <LinearLayout
 android:id="@+id/i8show_attention_rl"
 android:layout_width="match_parent"
 android:layout_height="60dp"
 android:orientation="horizontal">

 <RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="60dp"
  android:background="@color/white"
  android:gravity="center_vertical"
  android:padding="@dimen/I8d6">

  <ImageView
  android:id="@+id/i8show_attention_back"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerVertical="true"
  android:src="@drawable/i8live_nav_bcak" />

  <TextView
  android:id="@+id/i8show_attention_tittle"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:ellipsize="end"
  android:gravity="center"
  android:singleLine="true"
  android:text="我的签到"
  android:textColor="@android:color/black"
  android:textSize="@dimen/i8_text_size_18" />

 </RelativeLayout>
 </LinearLayout>

 <RelativeLayout
 android:id="@+id/rl_current_date"
 android:layout_width="match_parent"
 android:layout_height="49dp"
 android:layout_below="@id/i8show_attention_rl">

 <TextView
  android:id="@+id/tv_sign_year_month"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerVertical="true"
  android:layout_marginLeft="60dp"
  android:text="2017年11月"
  android:textColor="#000000"
  android:textSize="17sp" />
 </RelativeLayout>

 <com.i8dayou.an.zb.userinfo.signcalendar.SignCalendar
 android:id="@+id/sc_main"
 android:layout_width="match_parent"
 android:layout_height="320dp"
 android:layout_below="@id/rl_current_date"
 android:layout_marginLeft="15dp"
 android:layout_marginRight="15dp"
 android:layout_marginTop="15dp"
 android:clickable="true"></com.i8dayou.an.zb.userinfo.signcalendar.SignCalendar>

 <RelativeLayout
 android:id="@+id/rl_btn_sign"
 android:layout_width="135dp"
 android:layout_height="49dp"
 android:layout_centerInParent="true"
 android:layout_marginBottom="50dp"
 android:layout_alignParentBottom="true"
 android:background="@drawable/btn_sign_calendar"
 android:orientation="horizontal">

 <TextView
  android:id="@+id/btn_sign"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:layout_marginLeft="15dp"
  android:layout_marginRight="15dp"
  android:text="签 到"
  android:textColor="#fff"
  android:textSize="17sp" />
 </RelativeLayout>

 <RelativeLayout
 android:id="@+id/rl_get_gift_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#dd000000"
 android:visibility="gone"
 android:clickable="false">

 <ImageView
  android:id="@+id/iv_huode"
  android:layout_width="229dp"
  android:layout_height="59dp"
  android:layout_centerHorizontal="true"
  android:layout_marginTop="120dp"
  android:src="@drawable/i8live_huoede" />

 <RelativeLayout
  android:id="@+id/rl_sun"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_below="@id/iv_huode"
  android:layout_centerHorizontal="true">

  <ImageView
  android:id="@+id/iv_sun_bg"
  android:layout_width="200dp"
  android:layout_height="200dp"
  android:layout_centerInParent="true"
  android:src="@drawable/signed_on_rotate_bg" />

  <ImageView
  android:id="@+id/iv_sun"
  android:layout_width="98dp"
  android:layout_height="95dp"
  android:layout_centerInParent="true"
  android:src="@drawable/i8live_sun" />
 </RelativeLayout>

 <RelativeLayout
  android:id="@+id/rl_text_info"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_below="@id/rl_sun"
  android:layout_marginTop="10dp">

  <TextView
  android:id="@+id/tv_text_one"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerHorizontal="true"
  android:layout_marginLeft="20dp"
  android:layout_marginRight="20dp"
  android:text="第一天签到可获得20个人气币,经验200,免费弹幕1次"
  android:textColor="#ffffff"
  android:textSize="13sp" />
 </RelativeLayout>

 <RelativeLayout
  android:id="@+id/rl_queding_btn"
  android:layout_width="218dp"
  android:layout_height="38dp"
  android:layout_below="@id/rl_text_info"
  android:layout_centerHorizontal="true"
  android:layout_marginTop="19dp"
  android:background="@drawable/online_get_gift_btn">

  <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:text="确定"
  android:textColor="#ffffff"
  android:textSize="16sp" />
 </RelativeLayout>
 </RelativeLayout>

</RelativeLayout>

主界面Activity代码:

public class SignCalendarActivity extends Activity {
 private SignCalendar calendar;
 private String date;
 private TextView btn_sign;
 private TextView tv_sign_year_month;
 private SignCalendarReq signCalendarReq;
 private SignCalendarReq.DataBean dataBean;
 List<String> list = new ArrayList<String>();
 private int month;
 private int year;
 private RelativeLayout rlGetGiftData;
 private TextView tvGetSunValue;
 private ImageView ivSun;
 private ImageView ivSunBg;
 private RelativeLayout rlQuedingBtn;
 private RelativeLayout rlBtnSign;
 private ImageView signBack;

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

 //接收传递过来的初始化数据
 SignCalendarReq signCalendarReq = (SignCalendarReq) getIntent().getSerializableExtra("userInfos");

 month = Calendar.getInstance().get(Calendar.MONTH);
 year = Calendar.getInstance().get(Calendar.YEAR);

 SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
 Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
 date = formatter.format(curDate);
 calendar = (SignCalendar) findViewById(R.id.sc_main);
 btn_sign = (TextView) findViewById(R.id.btn_sign);
 tv_sign_year_month = (TextView) findViewById(R.id.tv_sign_year_month);
 rlGetGiftData = (RelativeLayout) findViewById(R.id.rl_get_gift_view);
 tvGetSunValue = (TextView) findViewById(R.id.tv_text_one);
 ivSun = (ImageView) findViewById(R.id.iv_sun);
 ivSunBg = (ImageView) findViewById(R.id.iv_sun_bg);
 signBack = (ImageView) findViewById(R.id.i8show_attention_back);
 rlQuedingBtn = (RelativeLayout) findViewById(R.id.rl_queding_btn);
 rlBtnSign = (RelativeLayout) findViewById(R.id.rl_btn_sign);

 tv_sign_year_month.setText(year + "年" + (month + 1) + "月");//设置日期

 if (signCalendarReq != null) {
  if (signCalendarReq.getState().getCode() == 1) {
  dataBean = signCalendarReq.getData();
  String signDay = dataBean.getSignDay();
  String[] splitDay = signDay.split(",");
  for (int i = 0; i < splitDay.length; i++) {
   if (Integer.parseInt(splitDay[i]) < 10) {
   list.add(year + "-" + (month + 1) + "-0" + splitDay[i]);
   } else {
   list.add(year + "-" + (month + 1) + "-" + splitDay[i]);
   }
  }
  calendar.addMarks(list, 0);

  if (dataBean.getIsSign() == 1) {//1是已签到,0是未签到
   rlBtnSign.setBackgroundResource(R.drawable.btn_sign_calendar_no);
   btn_sign.setText("已签到");
   rlBtnSign.setClickable(false);
  } else {
   rlBtnSign.setBackgroundResource(R.drawable.btn_sign_calendar);
   btn_sign.setText("签 到");
  }
  }
 }

 btn_sign.setOnClickListener(new View.OnClickListener() {

  @Override
  public void onClick(View v) {
  initSignCalendarData(2);//判断是否签到成功接口
  }
 });

 rlQuedingBtn.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  rlGetGiftData.setVisibility(View.GONE);
  }
 });

 signBack.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  finish();
  }
 });
 }

 //点击签到按钮网络请求数据
 private void initSignCalendarData(int requestType) {
 Map<String, String> map = new HashMap<String, String>();
 map.put("uid", I8ShowSharePre.getHomeId(getApplicationContext()));
 map.put("token", I8ShowSharePre.getToken(getApplicationContext()));
 map.put("type", requestType + "");
 I8ShowHttpEngine.getInstance().postNotJson(I8ShowAppClient.QUERY_GET_SIGN_CALENDAR_RESULT, map, new I8ShowHttpEngine.Listener() {
  @Override
  public void onResponseSuccess(Object data) {
  Log.i("aaa", "签到数据:" + data.toString());
  IsSignSuccessReq isSignSuccessReq = new Gson().fromJson(data.toString(), IsSignSuccessReq.class);
  if (isSignSuccessReq.getState().getCode() == 1) {
   rlGetGiftData.setVisibility(View.VISIBLE);
   rlBtnSign.setBackgroundResource(R.drawable.btn_sign_calendar_no);
   btn_sign.setText("已签到");

   if (isSignSuccessReq.getData().getValueType() == 0) {//0是sun
   ivSun.setImageResource(R.drawable.i8live_sun);
   tvGetSunValue.setText("恭喜获得" + isSignSuccessReq.getData().getAddValue() + "个");
   I8ShowUserInfoSP.setSunValue(getApplicationContext(), isSignSuccessReq.getData().getAllValue());//保存领取礼物后的数据
   } else if ((isSignSuccessReq.getData().getValueType() == 1)) {//1是zuan
   ivSun.setImageResource(R.drawable.i8live_zuan_sign);
   tvGetSunValue.setText("恭喜获得" + isSignSuccessReq.getData().getAddValue() + "个");
   I8SP.setDiamonds(getApplicationContext(), isSignSuccessReq.getData().getAllValue());
   }

   Animation operatingAnim = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate_anim_online_gift);
   LinearInterpolator lin = new LinearInterpolator();
   operatingAnim.setInterpolator(lin);
   ivSunBg.startAnimation(operatingAnim);

   //list.add("2017-11-18");
   list.add(date);
   // calendar.setCalendarDaysBgColor(list,R.drawable.bg_sign_today);
   calendar.addMarks(list, 0);
  }
  }

  @Override
  public void onResponseFailed(String failedMsg) {
  Log.i("aaa", "签到数据:" + failedMsg);
  }
 });
 }
}

日历自定义控件代码:

public class SignCalendar extends ViewFlipper implements GestureDetector.OnGestureListener {
 public static final int COLOR_BG_WEEK_TITLE = Color.parseColor("#FF5959"); // 星期标题背景颜色
 public static final int COLOR_TX_WEEK_TITLE = Color.parseColor("#FFFFFF"); // 星期标题文字颜色
 public static final int BEFORE_TODAY_BACKGROUND = Color.parseColor("#FFE4E4E4"); // 星期标题文字颜色
 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("#00ff00"); // 当天日历数字颜色
 public static final int COLOR_BG_THIS_DAY = Color.parseColor("#ffcccccc"); // 当天日历背景颜色
 public static final int COLOR_BG_CALENDAR = Color.parseColor("#FFFFFF"); // 日历背景色 

 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.anim_slice_in_left);
 push_left_out = AnimationUtils.loadAnimation(getContext(), R.anim.anim_slice_out_left);
 push_right_in = AnimationUtils.loadAnimation(getContext(), R.anim.anim_slice_in_right);
 push_right_out = AnimationUtils.loadAnimation(getContext(), R.anim.anim_slice_out_right);
 // 初始化第一个日历
 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;
 // 加入ViewFlipper
 addView(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.activity_horizontal_margin);
 // layout.setMargins(0, 0, 0, (int) (tb * 1.2));
 title.setLayoutParams(layout);
 oneCalendar.addView(title); 

 // 添加周末TextView
 for (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); 

 // 添加日期TextView
 for (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.bg);
  // col.setBackgroundResource(R.drawable.sign_dialog_day_bg);
  col.setClickable(false);
  row.addView(col); // 给每一个日子加上监听
  col.setOnClickListener(new OnClickListener() {
   @Override
   public 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.TOP);
   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.TOP);
   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_DAY);
    // view.setBackgroundResource(R.drawable.bg_sign_today);
   } else if (thisday.getMonth() == calendarday.getMonth()
    && thisday.getYear() == calendarday.getYear()) {
    // 绘制本月的颜色
    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();
 } 

 /**
 * 移除日历具体某个日期的背景色
 *
 * @param date
 */
 public void removeCalendarDayBgColor(Date date) {
 removeCalendarDayBgColor(format(date));
 } 

 /**
 * 移除日历具体某个日期的背景色
 *
 * @param date
 */
 public void removeCalendarDayBgColor(String date) {
 dayBgColorMap.remove(date);
 setCalendarDate();
 } 

 /**
 * 移除日历具体某个日期的背景色
 *
 */
 public void removeAllBgColor() {
 dayBgColorMap.clear();
 setCalendarDate();
 } 

 /**
 * 根据行列号获得包装每一个日子的LinearLayout
 *
 * @param row
 * @param col
 * @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();
 // dates[i][j]=2015-12-20等为要对比的日期,marksMap中包括了dates[i][j]时就进入下面的if语句
 if (marksMap.get(dates[i][j]) != null) {
  if (childCount < 2) {
  RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams((int) (tb * 2), (int) (tb * 2));
  // params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
  // params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
  params.setMargins(0, 0, 1, 1);
  params.addRule(RelativeLayout.CENTER_IN_PARENT);
  ImageView markView = new ImageView(getContext());
  markView.setImageResource(marksMap.get(dates[i][j]));
  markView.setLayoutParams(params); 

  //标记图片 可自定义
  //markView.setBackgroundResource(R.drawable.calendar_bg_tag);
  markView.setBackgroundResource(R.drawable.i8live_signin);

  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或4
 private 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) {
 } 

 @Override
 public 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;
 }
}

运行的效果图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android实现可滑动的自定义日历控件

    最近用到的一个日历控件,记录下,效果如图 代码下载地址:点击打开链接 布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical&q

  • Android学习教程之日历控件使用(7)

    本文实例为大家分享了Android日历控件的使用方法,供大家参考,具体内容如下 MainActivity.java代码: package siso.timessquare; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; p

  • Android自定义日历控件实例详解

    为什么要自定义控件 有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能:有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来提高代码的可复用性. 如何自定义控件 下面我通过我在github上开源的Android-CalendarView项目为例,来介绍一下自定义控件的方法.该项目中自定义的控件类名是CalendarView.这个自定义控件覆盖了一些自定义控件时常需要重写的一些方法. 构造函数 为了支持本控件既能使用xml布局文件声明,也可在ja

  • Android日历控件的实现方法

    本文实例为大家分享了Android日历控件的实现代码,供大家参考,具体内容如下 1.效果图: 2.弹窗Dialog:SelectDateDialog: public class SelectDateDialog { private static final String TAG = "SelectDateDialog"; private Dialog dialog; private TextView dateText; private int selectYear, selectMon

  • Android 一个日历控件的实现代码

    先看几张动态的效果图吧! 项目地址:https://github.com/Othershe/CalendarView 这里主要记录一下在编写日历控件过程中一些主要的点: 一.主要功能 1.支持农历.节气.常用节假日 2.日期范围设置,默认支持的最大日期范围[1900.1~2049.12] 3.默认选中日期设置 4.单选.多选 5.跳转到指定日期 6.通过自定义属性定制日期外观,以及简单的日期item布局配置 二.基本结构 我们要实现的日历控件采用ViewPager作为主框架,CalendarVi

  • Android实现日历控件示例代码

    做的是一个酒店的项目,可以选择入住和离开的日期.声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助.喜欢的给个好评.谢谢啦!祝生活愉快! 先上图 第一步,搭建布局xml <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_w

  • Android使用GridLayout绘制自定义日历控件

    效果图 思路:就是先设置Gridlayout的行列数,然后往里面放置一定数目的自定义日历按钮控件,最后实现日历逻辑就可以了. 步骤: 第一步:自定义日历控件(初步) 第二步:实现自定义单个日期按钮控件 第三步:将第二步得到的控件动态添加到第一步的布局中,并实现日期逻辑 第四步:编写单个日期点击监听器接口 第一步:自定义日历控件(初步) <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln

  • Android可签到日历控件的实现方法

    最近在公司的功能需求中,需要实现可以签到的日历,签到后在签到过的日期做标志.本功能参考了网上一些大神的日历控件,在此基础上进行修改,已满足本公司的需求,现已完成,记录一下. 布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_wi

  • Android自定义实现日历控件

    本文实例为大家分享了Android自定义实现日历控件的具体代码,供大家参考,具体内容如下 1. Calendar类 2. 布局 创建calendar_layout.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="20sp" android:orientation="vertical" android:l

  • ASP.NET中日历控件和JS版日历控件的使用方法(第5节)

    今天小编带大家以做任务的形式了解ASP.NET中日历控件的使用方法,主要任务内容: 1.添加一个日历,设置日期以蓝色的完整名称显示,周末以黄色背景红色文字显示,而当前日期使用绿色背景显示,用户可以选择一天.一周或整个月,被选的天/周/月使用灰色背景色来显示.当选中一个日期后,把时间显示在下面的一个文本框中,效果如图所示: 2.设计一个注册页面,使用js日历控件帮助用户输入出生日期.效果如图所示: 学习项目一  Calendar日历控件 1.在站点下创建一个Calendar页面,并在页面上拖放一个

  • Android自带倒计时控件Chronometer使用方法详解

    公司的以前的项目,看到使用了这个Android自带的倒计时控件Chronometer,现在整合了一下 先看看效果: <Chronometer android:id="@+id/chronometer" android:layout_width="wrap_content" android:layout_height="30dp" /> <Button android:onClick="start" andro

  • laydate日历控件使用方法详解

    本文实例为大家分享了laydate日历控件的使用方法,供大家参考,具体内容如下 var start = { elem: '#start_0', format: 'YYYY-MM-DD', max: laydate.now(-1), istime: false, istoday: false, choose: function (datas) { $("input[name='TimeStart']").parent().next(".timeError").addC

  • layui-laydate时间日历控件使用方法详解

    本文实例为大家分享了laydate时间日历控件的使用方法,供大家参考,具体内容如下 layui下载地址:http://www.layui.com/ 此控件可使用layui或者独立版的layDate,两者初始化有些不同 在 layui 模块中使用layui.code <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>layDate快速使用</title&

随机推荐