Android可签到的日历控件

作者: 龙旋之谷 | 来源:发表于2019-08-05 09:28 被阅读45次

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

    运行的效果图:

    未签到

    布局文件:

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

    以上代码会出现初始化无效,公众号已同步修复后的demo。
    需要Demo的童鞋,底部公众号回复 "签到日历"即可获取。

    我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2mprvb5k4yio4


    以下是个人公众号(longxuanzhigu),之后发布的文章会同步到该公众号,方便交流学习Android知识及分享个人爱好文章:

    这里写图片描述

    相关文章

      网友评论

        本文标题:Android可签到的日历控件

        本文链接:https://www.haomeiwen.com/subject/tplpdctx.html