摸滚打爬在Android界小菜鸟,突然静下心想想自己都做过些什么呢!留下些什么呢!感觉自己老是copy别人的东西自己都不好意思了,于是今天就 来分享下自己最近写项目中的一个自定义日历控件 (翻阅了各大开源日历都没有合适的),希望大家多多指点,第一次写博客如果有不足之处,请尽管喷。

   

因为自己不知道怎么描述那我就直接上代码了。


因为这个是自己写的demo adapter等没有分开写, 自己分开写Adapter,如果你觉得对你有用可以自己,放在不同的文件夹下面。

public class MainActivity extends AppCompatActivity {

    private ListView mListView;
    private CalendarListAdapter mAdapter;

    private List calendarModels;

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

        calendarModels = getData();

        mListView = (ListView) findViewById(R.id.listview);

        mAdapter = new CalendarListAdapter(this);
        mListView.setAdapter(mAdapter);

        mAdapter.setDataSource(calendarModels);
        mAdapter.notifyDataSetChanged();
    }

    private int lastPosition = 0;

    private List getData() {
        List calendarModels = new ArrayList();
        int year = 2017;

        for (int index = 0; index < 12; index++) {
            CalendarModel calendarModel = new CalendarModel();
            calendarModel.setMonthIndex(index);
            calendarModel.setMonthDays(getDaysInMonth(index, year));
            if (index == 0) {
                calendarModel.setFirstPosition(6);
                calendarModel.setLastPosition(1);
                lastPosition = 1;
            } else {
                calendarModel.setFirstPosition(lastPosition + 1);
                lastPosition = (getDaysInMonth(index, year) + lastPosition) % 7;
                calendarModel.setLastPosition(lastPosition);

            }

            calendarModels.add(calendarModel);
        }

        return calendarModels;
    }

    private int getDaysInMonth(int month, int year) {
        switch (month) {
            case Calendar.JANUARY:
            case Calendar.MARCH:
            case Calendar.MAY:
            case Calendar.JULY:
            case Calendar.AUGUST:
            case Calendar.OCTOBER:
            case Calendar.DECEMBER:
                return 31;
            case Calendar.APRIL:
            case Calendar.JUNE:
            case Calendar.SEPTEMBER:
            case Calendar.NOVEMBER:
                return 30;
            case Calendar.FEBRUARY:
                return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 29 : 28;
            default:
                throw new IllegalArgumentException("Invalid Month");
        }
    }

    class CalendarListAdapter extends BaseAdapter {

        private Context mContext;
        private List dataSource;

        public void setDataSource(List dataSource) {
            this.dataSource = dataSource;
        }

        public CalendarListAdapter(Context context) {
            mContext = context;
        }

        @Override
        public int getCount() {
            return dataSource == null ? 0 : dataSource.size();
        }

        @Override
        public CalendarModel getItem(int i) {
            return dataSource == null ? null : dataSource.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            if (view == null) {
                viewHolder = new ViewHolder();
                view = LayoutInflater.from(mContext).inflate(R.layout.item_list_calendar, null);
                viewHolder.titleView = (TextView) view.findViewById(R.id.title_tv);
                viewHolder.gridView = (CustomGridView) view.findViewById(R.id.days_grid);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            CalendarModel calendarModel = getItem(i);
            if (calendarModel != null) {
                viewHolder.titleView.setText(String.valueOf(calendarModel.getMonthIndex() + 1));

                int first = calendarModel.getFirstPosition();
                int last = calendarModel.getLastPosition();

                CalendarGridAdapter adapter = new CalendarGridAdapter(mContext,calendarModel.getMonthIndex() + 1);
                viewHolder.gridView.setAdapter(adapter);

                List dataSource = new ArrayList();
                for (int index = 0; index < first; index++) {
                    DayModel dayModel = new DayModel();
                    dayModel.setDayIndex(0);
                    dayModel.setMonthIndex(calendarModel.getMonthIndex() + 1);
                    dataSource.add(dayModel);
                }

                int days = calendarModel.getMonthDays();
                for (int index = 0; index < days; index++) {
                    DayModel dayModel = new DayModel();
                    dayModel.setDayIndex(index + 1);
                    dataSource.add(dayModel);
                }

                adapter.setDataSource(dataSource);
                adapter.notifyDataSetChanged();
            }

            return view;
        }

        class ViewHolder {
            TextView titleView;
            CustomGridView gridView;
        }
    }

    private List monthDayModels = new ArrayList();

    class CalendarGridAdapter extends BaseAdapter {
        int curentMonth;
        private Context mContext;
        private List dataSource;



        List>  limitTime = new ArrayList>();

        public void setDataSource(List dataSource) {
            this.dataSource = dataSource;
        }

        public CalendarGridAdapter(Context context,int curentMonth) {
            mContext = context;
            this.curentMonth = curentMonth;
            //模拟后台指定的开始时间和结束时间
            HashMap map1 = new HashMap<>();
            map1.put("startTime",1490716800000L);
            map1.put("endTime",1491580799000L);
            limitTime.add(map1);

            HashMap map2 = new HashMap<>();
            map2.put("startTime",1491926800000L);
            map2.put("endTime",1492444799000L);
            limitTime.add(map2);

        }

        @Override
        public int getCount() {
            return dataSource == null ? 0 : dataSource.size();
        }

        @Override
        public DayModel getItem(int i) {
            return dataSource == null ? null : dataSource.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            final ViewHolder viewHolder;
            if (view == null) {
                viewHolder = new ViewHolder();
                view = LayoutInflater.from(mContext).inflate(R.layout.item_grid_calendar, null);
                viewHolder.titleView = (TextView) view.findViewById(R.id.day_tv);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }
            final View state_line = view.findViewById(R.id.state_line);
            final DayModel dayModel = getItem(i);
            if (dayModel != null && dayModel.getDayIndex() != 0) {
                viewHolder.titleView.setText(String.valueOf(dayModel.getDayIndex()));
                viewHolder.titleView.setVisibility(View.VISIBLE);
            } else {
                viewHolder.titleView.setVisibility(View.INVISIBLE);
            }

            int month = dayModel.getMonthIndex();
            final int day = dayModel.getDayIndex();

            int size = monthDayModels.size();
            for (int index = 0; index < size; index++) {
                MonthDayModel monthDayModel =  monthDayModels.get(index);
                if (monthDayModel != null) {
                    if (monthDayModel.getDay() == day && monthDayModel.getMonth() == month) {
                        viewHolder.titleView.setTextColor(Color.parseColor("#FF0000"));
                    } else {
                        viewHolder.titleView.setTextColor(Color.parseColor("#999999"));
                    }
                } else {
                    viewHolder.titleView.setTextColor(Color.parseColor("#999999"));
                }
            }
            String dateStr = "2017-"+curentMonth+"-"+day+" 00:00:00";
//            Log.e("date",dateStr);
            final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date date = simpleDateFormat.parse(dateStr);
                final long timeSecond = date.getTime();
                boolean isContain = isContaingDate(timeSecond);
                if(isContain){
                    viewHolder.titleView.setTextColor(Color.parseColor("#FF0000"));
//                    state_line.setVisibility(View.VISIBLE);
                }else{
                    viewHolder.titleView.setTextColor(Color.parseColor("#999999"));
//                    state_line.setVisibility(View.GONE);
                }
                if(checkStartTime != 0 && checkEndTime != 0){
                    //选择了开始时间和结束时间,并且显示区间的下划线
                    if(timeSecond >= checkStartTime && timeSecond <= checkEndTime){
                        state_line.setVisibility(View.VISIBLE);
                    }
                }else{
                    //当天的最后时刻
                    String todayEnd = "2017-"+curentMonth+"-"+day+" 23:59:59";
                    //获取当天最后时刻的好描述
                    long todaySecondEnd = simpleDateFormat.parse(todayEnd).getTime();
                    //如果选择的开始时间大于当天凌晨0点0分0秒 并且小于当天时间23点59分59秒的时候
                    //也就是说,只选择了一个开始时间  并且这个开始时间在当天的范围之内 就显示下划线
                    if(checkStartTime >= timeSecond && checkStartTime <= todaySecondEnd){
                        state_line.setVisibility(View.VISIBLE);
                    }else{
                        state_line.setVisibility(View.GONE);
                    }
                }

                viewHolder.titleView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        boolean isContain = isContaingDate(timeSecond);
                        if(!isContain){
                            //在服务器的区间内,才能点击
                            Toast.makeText(mContext,"所选日期不在要求范围内!",Toast.LENGTH_SHORT).show();
                            return;
                        }
                        if(checkStartTime == 0 && checkEndTime == 0){
                            //开始时间和结束时间均为空,则先选择开始时间
                            String dateStr = "2017-"+curentMonth+"-"+day+" 00:00:00";
                            try {
                                Date date  = simpleDateFormat.parse(dateStr);
                                checkStartTime = date.getTime();
                                notifyDataSetChanged();
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }else if(checkEndTime == 0 && checkStartTime != 0){
                            //开始时间不为空,且结束时间为空
                            String dateStr = "2017-"+curentMonth+"-"+day+" 23:59:59";
                            try {
                                Date date  = simpleDateFormat.parse(dateStr);
                                long checkTime = date.getTime();
                                if(checkTime <= checkStartTime){
                                    Toast.makeText(mContext,"结束时间应该大于开始时间!",Toast.LENGTH_SHORT).show();
                                    return;
                                }else{
                                    boolean issameSpace = isInSameSpace(checkStartTime,checkTime);
                                    if(issameSpace){
                                        checkEndTime = checkTime;
                                    }else{
                                        Toast.makeText(mContext,"开始时间和结束时间不在同一个可选区间内!",Toast.LENGTH_SHORT).show();
                                        return;
                                    }
                                }
                                notifyDataSetChanged();
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }else{
                            //当开始时间不为空且结束时间也不为空,这个时候,就设置开始时间为当前时间,结束时间为0
                            String dateStr = "2017-"+curentMonth+"-"+day+" 00:00:00";
                            try {
                                Date date  = simpleDateFormat.parse(dateStr);
                                checkStartTime = date.getTime();
                                checkEndTime = 0;
                                notifyDataSetChanged();
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return view;
        }


        /**
         * 所选的开始时间和结束时间是否在同一个区间内
         * @param startTime
         * @param endTime
         * @return
         */
        boolean isInSameSpace(long startTime,long endTime){
            for(HashMap map:limitTime){
                long timeStart = map.get("startTime");
                long timeEnd = map.get("endTime");
                if(startTime >= timeStart && startTime <= timeEnd
                        && endTime >= timeStart && endTime <= timeEnd){
                    return true;
                }
            }
            return false;
        }

        long checkStartTime = 0,checkEndTime = 0;


        private boolean isContaingDate(long timeSecond) {
            for(HashMap map:limitTime){
                long timeStart = map.get("startTime");
                long timeEnd = map.get("endTime");
                if(timeSecond >= timeStart && timeSecond <= timeEnd){
                    return true;
                }
            }
            return false;
        }


        class ViewHolder {
            TextView titleView;
        }
    }

}

后期我会把代码整理好开源给小伙伴们......

Demo地址:http://download.csdn.net/detail/bimromatic/9837950


更多相关文章

  1. Android(安卓)优化电池使用时间 ——监控电池电量和充电状态
  2. Android(安卓)进阶——实现周期性任务调度的几种攻略详解
  3. 修改android 4.4系统下面的休眠时间,只留下永不休眠选项
  4. android listview adapter中设置点击直接position被重用问题解决
  5. Android和Linux的时间戳
  6. 自定义样式日期时间选择对话框控件(精简版)
  7. 针对Android(安卓)模拟器启动慢的问题,长时间显示 Android(安卓)L
  8. Android滚轮时间选择控件(可扩展自定义)
  9. android 可以精确到秒级的时间选择器

随机推荐

  1. Android(安卓)Binder设计与实现(1) – 设计
  2. Appium 环境配置
  3. android编译系统 - pathmap.mk
  4. Android(安卓)Camera2 拍照(三)——切换摄
  5. Android(安卓)RxJava使用介绍(四) RxJava的
  6. android studio 打包自动生成版本号与日
  7. android vlc源码编译
  8. Android(安卓)Library Project 使用问题
  9. [Android]照相机范例代码
  10. android string.xml中显示特殊字符