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

以上代碼會出現初始化無效,公衆號已同步修復後的demo。
需要Demo的童鞋,底部公衆號回覆 "簽到日曆"即可獲取。

運行的效果圖:

未簽到

以下是個人公衆號(longxuanzhigu),之後發佈的文章會同步到該公衆號,方便交流學習Android知識及分享個人愛好文章:

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章