Android 自定义自由选择时间区间的日历控件

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

  

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


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

public class MainActivity extends AppCompatActivity {

    private ListView mListView;
    private CalendarListAdapter mAdapter;

    private List<CalendarModel> 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<CalendarModel> getData() {
        List<CalendarModel> calendarModels = new ArrayList<CalendarModel>();
        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<CalendarModel> dataSource;

        public void setDataSource(List<CalendarModel> 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<DayModel> dataSource = new ArrayList<DayModel>();
                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<MonthDayModel> monthDayModels = new ArrayList<MonthDayModel>();

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



        List<HashMap<String,Long>>  limitTime = new ArrayList<HashMap<String,Long>>();

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

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

            HashMap<String,Long> 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<String,Long> 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<String,Long> 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


0 0
原创粉丝点击