package com.bigfat.scrolldemo; import android.graphics.Color; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewTreeObserver; import android.widget.ArrayAdapter; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextView; import java.util.ArrayList; import java.util.Calendar; public class MainActivity extends ActionBarActivity implements View.OnClickListener { private static final String TAG = MainActivity.class.getSimpleName(); //颜色值 public static int headerBgColor; public static int headerNormalTextColor; public static int headerHolidayTextColor; public static int dayCurrentMonthText; public static int dayHolidayText; public static int daySelectText; public static int dayNormalMonthText; public static int todayBgColor; public static int selectedDayBgColor; public static int reminderColor; //测量值 int calendarCurrentWeekHeight;//日历当前周那一行距离顶部的高度 int screenWidth;//屏幕宽度 int cellWidth;//日历单元格宽度 //标识值 private static int firstDayOfWeek = Calendar.SUNDAY; private int currentMonth; private int currentYear; private boolean isSelectedWeekInCalendar; //容器类 private ScrollView scrollView; private LinearLayout llCalendarTop; private LinearLayout llCalendarContent; private LinearLayout llCalendarContentFloat; //控件 private TextView tvCurrentDate; private ImageButton btnPre; private ImageButton btnNext; private ListView listView; private ArrayList<DateWidgetDayCell> days = new ArrayList<>(); private ArrayList<DateWidgetDayCell> daysFloat = new ArrayList<>(); //数据 private ArrayList<String> data;//日程列表 private Calendar calStartDate = Calendar.getInstance();//日历起始日期 private Calendar calToday = Calendar.getInstance();//今天 private Calendar calSelected = Calendar.getInstance();//当前选中日期 // 点击日历,触发事件 private DateWidgetDayCell.OnItemClick onDayCellClickEvent = new DateWidgetDayCell.OnItemClick() { public void OnClick(DateWidgetDayCell item) { setCalSelected(item.getDate()); } }; public static Calendar GetTodayDate() { Calendar cal_Today = Calendar.getInstance(); cal_Today.set(Calendar.HOUR_OF_DAY, 0); cal_Today.set(Calendar.MINUTE, 0); cal_Today.set(Calendar.SECOND, 0); cal_Today.setFirstDayOfWeek(firstDayOfWeek); return cal_Today; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMeasure(); initColor(); initData(); initView(); initCalendarView(); initListView(); initEvent(); } private void initMeasure() { DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); screenWidth = dm.widthPixels; cellWidth = screenWidth / 7 + 1; } private void initColor() { headerBgColor = this.getResources().getColor(R.color.calendar_header_bg); headerHolidayTextColor = this.getResources().getColor(R.color.calendar_header_holiday_text); headerNormalTextColor = this.getResources().getColor(R.color.calendar_header_normal_text); dayNormalMonthText = this.getResources().getColor(R.color.calendar_day_normal_month_text); dayCurrentMonthText = this.getResources().getColor(R.color.calendar_day_current_month_text); dayHolidayText = this.getResources().getColor(R.color.calendar_day_holiday_text); daySelectText = this.getResources().getColor(R.color.calendar_day_select_text); todayBgColor = this.getResources().getColor(R.color.calendar_day_today_bg); selectedDayBgColor = this.getResources().getColor(R.color.calendar_day_select_bg); reminderColor = this.getResources().getColor(R.color.calendar_reminder); } private void initData() { data = new ArrayList<>(); for (int i = 0; i < 30; i++) { data.add("item_" + i); } } private void initView() { scrollView = (ScrollView) findViewById(R.id.scv_frag_calendar); llCalendarTop = (LinearLayout) findViewById(R.id.ll_frag_calendar_top); llCalendarContent = (LinearLayout) findViewById(R.id.ll_frag_calendar_content); llCalendarContentFloat = (LinearLayout) findViewById(R.id.ll_frag_calendar_content_float); tvCurrentDate = (TextView) findViewById(R.id.tv_frag_calendar_current_date); btnPre = (ImageButton) findViewById(R.id.btn_frag_calendar_pre); btnNext = (ImageButton) findViewById(R.id.btn_frag_calendar_next); listView = (ListView) findViewById(R.id.lv_frag_calendar); } private void initCalendarView() { calStartDate.setTimeInMillis(System.currentTimeMillis()); calStartDate.setFirstDayOfWeek(firstDayOfWeek); calToday = GetTodayDate(); calSelected.setTimeInMillis(calToday.getTimeInMillis()); //绘制日历空白模板 llCalendarTop.addView(generateCalendarTop()); llCalendarContent.addView(generateCalendarContent()); llCalendarContentFloat.addView(generateCalendarContentFloat()); // 计算本月日历中的第一天(一般是上月的某天),并更新日历 updateCalendarStartDate(); } private void initListView() { ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.list_item, R.id.list_item_tv, data); listView.setAdapter(adapter); int itemHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()); int lvHeight = itemHeight * data.size() + listView.getDividerHeight() * (data.size() - 1); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) listView.getLayoutParams(); lp.height = lvHeight; listView.setLayoutParams(lp); } private void initEvent() { btnPre.setOnClickListener(this); btnNext.setOnClickListener(this); scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { executeScvScrollEvent(); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_frag_calendar_pre://上个月 Log.i(TAG, "btn_frag_calendar_pre"); currentMonth--; if (currentMonth == -1) { currentMonth = 11; currentYear--; } calStartDate.set(Calendar.MONTH, currentMonth); calStartDate.set(Calendar.YEAR, currentYear); updateCalendarStartDate(); break; case R.id.btn_frag_calendar_next://下个月 Log.i(TAG, "btn_frag_calendar_next"); currentMonth++; if (currentMonth == 12) { currentMonth = 0; currentYear++; } calStartDate.set(Calendar.MONTH, currentMonth); calStartDate.set(Calendar.YEAR, currentYear); updateCalendarStartDate(); break; } } /** * 处理界面滚动事件 */ private void executeScvScrollEvent() { // Log.i(TAG, "scrollView.getY()--->" + scrollView.getScrollY()); // Log.i(TAG, "calendarCurrentWeekHeight--->" + calendarCurrentWeekHeight); if (isSelectedWeekInCalendar && scrollView.getScrollY() > calendarCurrentWeekHeight) { llCalendarContentFloat.setVisibility(View.VISIBLE); } else { llCalendarContentFloat.setVisibility(View.GONE); } } /** * 设置当前选中日期 */ private void setCalSelected(Calendar calendar) { calSelected.setTimeInMillis(calendar.getTimeInMillis()); updateCalendarSelectedWeekHeight(); // if (adapter != null) // adapter.jump2today(item.getDate().getTime()); updateCalendar(); } /** * 更新当天日期和被选中日期 */ private void updateCalendarStartDate() { currentMonth = calStartDate.get(Calendar.MONTH); currentYear = calStartDate.get(Calendar.YEAR); calStartDate.set(Calendar.DAY_OF_MONTH, 1); calStartDate.set(Calendar.HOUR_OF_DAY, 0); calStartDate.set(Calendar.MINUTE, 0); calStartDate.set(Calendar.SECOND, 0); //默认选择当前月第一天 calSelected.setTimeInMillis(calStartDate.getTimeInMillis()); //计算当前月日历视图中真正的起始天 int iDay = 0; int iStartDay = firstDayOfWeek; if (iStartDay == Calendar.MONDAY) { iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY; if (iDay < 0) iDay = 6; } if (iStartDay == Calendar.SUNDAY) { iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; if (iDay < 0) iDay = 6; } calStartDate.add(Calendar.DAY_OF_WEEK, -iDay); //根据当前选择更新视图 setCalSelected(calSelected); //刷新顶部当前月文本 updateCurrentMonthDisplay(); //判断当前选择周(天)是否在日历列表中,作为顶部周视图是否显示的判断 long startMills = calStartDate.getTimeInMillis(); long selectedMills = calSelected.getTimeInMillis(); isSelectedWeekInCalendar = selectedMills >= startMills && selectedMills <= startMills + 41 * 24 * 60 * 60 * (long) 1000; } /** * 更新日历标题上显示的年月 */ private void updateCurrentMonthDisplay() { String date = calStartDate.get(Calendar.YEAR) + "年" + (currentMonth + 1) + "月"; tvCurrentDate.setText(date); } private View generateCalendarTop() { LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL); layRow.setBackgroundColor(Color.parseColor("#f3f3f3")); layRow.setPadding(0, 0, 0, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics())); DateWidgetDayHeader day; int iWeekDay; for (int iDay = 0; iDay < 7; iDay++) { day = new DateWidgetDayHeader(this, cellWidth); day.setBackgroundColor(Color.parseColor("#f3f3f3")); iWeekDay = DayStyle.getWeekDay(iDay, firstDayOfWeek); day.setData(iWeekDay); layRow.addView(day); } return layRow; } private View generateCalendarContent() { LinearLayout layContentDays = createLayout(LinearLayout.VERTICAL); days.clear(); for (int iRow = 0; iRow < 6; iRow++) { layContentDays.addView(generateCalendarRow()); } return layContentDays; } private View generateCalendarContentFloat() { LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL); for (int iDay = 0; iDay < 7; iDay++) { DateWidgetDayCell dayCell = new DateWidgetDayCell(this, cellWidth, cellWidth * 4 / 5); dayCell.setItemClick(onDayCellClickEvent); daysFloat.add(dayCell); layRow.addView(dayCell); } return layRow; } /** * 生成日历中的一行,仅生成View,没有数据 */ private View generateCalendarRow() { LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL); for (int iDay = 0; iDay < 7; iDay++) { DateWidgetDayCell dayCell = new DateWidgetDayCell(this, cellWidth, cellWidth * 4 / 5); dayCell.setItemClick(onDayCellClickEvent); days.add(dayCell); layRow.addView(dayCell); } return layRow; } private void updateCalendar() { updateCalendarSelectedWeekHeight(); // 更新日历 Calendar calCalendar = Calendar.getInstance(); final boolean bIsSelection = (calSelected.getTimeInMillis() != 0); final int iSelectedYear = calSelected.get(Calendar.YEAR); final int iSelectedMonth = calSelected.get(Calendar.MONTH); final int iSelectedDay = calSelected.get(Calendar.DAY_OF_MONTH); calCalendar.setTimeInMillis(calStartDate.getTimeInMillis()); //当前选中周起始索引 long currentWeekStartDayIndex = (calSelected.getTimeInMillis() - calStartDate.getTimeInMillis()) / 1000 / 60 / 60 / 24 / 7 * 7; Log.i(TAG, "updateCalendar"); Log.i(TAG, "currentMonth--->" + currentMonth); for (int i = 0; i < days.size(); i++) { final int iYear = calCalendar.get(Calendar.YEAR); final int iMonth = calCalendar.get(Calendar.MONTH); final int iDay = calCalendar.get(Calendar.DAY_OF_MONTH); final int iDayOfWeek = calCalendar.get(Calendar.DAY_OF_WEEK); DateWidgetDayCell dayCell = days.get(i); // 判断是否当天 boolean bToday = false; if (calToday.get(Calendar.YEAR) == iYear) { if (calToday.get(Calendar.MONTH) == iMonth) { if (calToday.get(Calendar.DAY_OF_MONTH) == iDay) { bToday = true; } } } // 是否是周末 boolean bHoliday = false; if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY)) bHoliday = true; // 是否被选中 boolean bSelected = false; if (bIsSelection) if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) { bSelected = true; } // 是否有日程 boolean hasRecord = false; // if (data != null) { // hasRecord = data.containsKey(DateUtil.getStr( // calCalendar.getTime(), // DateUtil.DAY)); // } //设置日期Cell状态 dayCell.setData(iYear, iMonth, iDay, bToday, bHoliday, currentMonth, hasRecord, bSelected); dayCell.invalidate(); //如果是当前周,则顶部当前周数据也要设置 if (i >= currentWeekStartDayIndex && i < currentWeekStartDayIndex + 7) { DateWidgetDayCell dayCellFloat = daysFloat.get(i - (int) currentWeekStartDayIndex); dayCellFloat.setData(iYear, iMonth, iDay, bToday, bHoliday, currentMonth, hasRecord, bSelected); dayCellFloat.invalidate(); } //下一天 calCalendar.add(Calendar.DAY_OF_MONTH, 1); } llCalendarContent.invalidate(); llCalendarContentFloat.invalidate(); } /** * 计算当前周这一行之前日历的高度 */ private void updateCalendarSelectedWeekHeight() { llCalendarContentFloat.post(new Runnable() { @Override public void run() { //计算当前周之前一共有几行 long rows = (calSelected.getTimeInMillis() - calStartDate.getTimeInMillis()) / 1000 / 60 / 60 / 24 / 7; calendarCurrentWeekHeight = llCalendarContentFloat.getHeight() * (int) rows; executeScvScrollEvent(); } }); } // 生成布局 private LinearLayout createLayout(int iOrientation) { LinearLayout lay = new LinearLayout(this); lay.setLayoutParams(new LinearLayout.LayoutParams( android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT)); lay.setOrientation(iOrientation); lay.setBackgroundColor(Color.WHITE); return lay; } }