我是靠谱客的博主 纯情高跟鞋,这篇文章主要介绍Android实现可滑动的自定义日历控件,现在分享给大家,希望可以做个参考。

最近用到的一个日历控件,记录下,效果如图

代码下载地址:点击打开链接

布局文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="visible"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/bg_gray" android:orientation="horizontal"> <ImageView android:id="@+id/prevMonth" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="1" android:src="@drawable/prev_month" /> <TextView android:id="@+id/currentMonth" android:layout_width="0dp" android:layout_height="35dp" android:layout_weight="3" android:gravity="center" android:text="2016年9月" android:textColor="@color/black" android:textSize="18sp" /> <ImageView android:id="@+id/nextMonth" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="1" android:src="@drawable/next_month" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="20dp" android:background="@color/bg_gray"> <TextView style="@style/weekName" android:text="周日" android:textColor="@color/green" /> <TextView style="@style/weekName" android:text="周一" /> <TextView style="@style/weekName" android:text="周二" /> <TextView style="@style/weekName" android:text="周三" /> <TextView style="@style/weekName" android:text="周四" /> <TextView style="@style/weekName" android:text="周五" /> <TextView style="@style/weekName" android:text="周六" android:textColor="@color/green" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/line" /> <ViewFlipper android:id="@+id/flipper" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/line" android:padding="1dp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/line" /> </LinearLayout>

日历PopCalendar.class的代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
public class PopCalendar extends PopupWindow implements View.OnClickListener { private View contentView; private Context mContext; private WindowManager windowManager; private GestureDetector gestureDetector = null; private CalendarAdapter calV = null; private ViewFlipper flipper = null; private GridView gvCalendar = null; private static int jumpMonth = 0; // 每次滑动,增加或减去一个月,默认为0(即显示当前月) private static int jumpYear = 0; // 滑动跨越一年,则增加或者减去一年,默认为0(即当前年) private int yearC = 0; private int monthC = 0; private int dayC = 0; private String currentDate = ""; //当前年月,显示在日历顶端 private TextView currentMonthTv; //上个月,下个月的图标 private ImageView prevMonthIv; private ImageView nextMonthIv; public PopCalendar(final Activity context) { this.mContext = context; this.windowManager = context.getWindowManager();; Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d"); currentDate = sdf.format(date); // 当期日期 yearC = Integer.parseInt(currentDate.split("-")[0]); monthC = Integer.parseInt(currentDate.split("-")[1]); dayC = Integer.parseInt(currentDate.split("-")[2]); jumpMonth = 0; jumpYear = 0; //设置PopWindow的属性 LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); contentView = inflater.inflate(R.layout.pop_calendar, null); this.setContentView(contentView); this.setWidth(WindowManager.LayoutParams.FILL_PARENT); this.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); this.setFocusable(true); this.setOutsideTouchable(true); this.update(); ColorDrawable dw = new ColorDrawable(0000000000); this.setBackgroundDrawable(dw); currentMonthTv = (TextView) contentView.findViewById(R.id.currentMonth); prevMonthIv = (ImageView) contentView.findViewById(R.id.prevMonth); nextMonthIv = (ImageView) contentView.findViewById(R.id.nextMonth); setListener(); gestureDetector = new GestureDetector(mContext, new MyGestureListener()); flipper = (ViewFlipper) contentView.findViewById(R.id.flipper); flipper.removeAllViews(); calV = new CalendarAdapter(mContext, mContext.getResources(), jumpMonth, jumpYear, yearC, monthC, dayC); addGridView(); gvCalendar.setAdapter(calV); flipper.addView(gvCalendar, 0); addTextToTopTextView(currentMonthTv); } private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1.getX() - e2.getX() > 120) { // 像左滑动 enterNextMonth(); return true; } else if (e1.getX() - e2.getX() < -120) { // 向右滑动 enterPrevMonth(); return true; } return false; } } /** * 移动到下一个月 * */ private void enterNextMonth() { addGridView(); // 添加一个gridView jumpMonth++; // 下一个月 calV = new CalendarAdapter(mContext, mContext.getResources(), jumpMonth, jumpYear, yearC, monthC, dayC); gvCalendar.setAdapter(calV); addTextToTopTextView(currentMonthTv); // 移动到下一月后,将当月显示在头标题中 flipper.addView(gvCalendar, 1); flipper.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_in)); flipper.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_out)); flipper.showNext(); flipper.removeViewAt(0); } /** * 移动到上一个月 * */ private void enterPrevMonth() { addGridView(); // 添加一个gridView jumpMonth--; // 上一个月 calV = new CalendarAdapter(mContext, mContext.getResources(), jumpMonth, jumpYear, yearC, monthC, dayC); gvCalendar.setAdapter(calV); addTextToTopTextView(currentMonthTv); // 移动到上一月后,将当月显示在头标题中 flipper.addView(gvCalendar, 1); flipper.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_right_in)); flipper.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_right_out)); flipper.showPrevious(); flipper.removeViewAt(0); } /** * 添加头部的年份 闰哪月等信息 * @param view */ public void addTextToTopTextView(TextView view) { StringBuffer textDate = new StringBuffer(); textDate.append(calV.getShowYear()).append("年").append(calV.getShowMonth()).append("月").append("t"); view.setText(textDate); } private void addGridView() { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT); // 取得屏幕的宽度和高度 Display display = windowManager.getDefaultDisplay(); int Width = display.getWidth(); int Height = display.getHeight(); gvCalendar = new GridView(mContext); gvCalendar.setNumColumns(7); gvCalendar.setColumnWidth(40); // gridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); if (Width == 720 && Height == 1280) { gvCalendar.setColumnWidth(40); } gvCalendar.setGravity(Gravity.CENTER_VERTICAL); gvCalendar.setSelector(new ColorDrawable(Color.TRANSPARENT)); // 去除gridView边框 gvCalendar.setVerticalSpacing(2); gvCalendar.setHorizontalSpacing(2); gvCalendar.setOnTouchListener(new View.OnTouchListener() { // 将gridView中的触摸事件回传给gestureDetector public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub return PopCalendar.this.gestureDetector.onTouchEvent(event); } }); gvCalendar.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { // TODO Auto-generated method stub // 点击任何一个item,得到这个item的日期(排除点击的是周日到周六(点击不响应)) int startPosition = calV.getStartPosition(); int endPosition = calV.getEndPosition(); if (startPosition <= position + 7 && position <= endPosition - 7) { String scheduleDay = calV.getDateByClickItem(position); // 这一天的阳历 String scheduleYear = calV.getShowYear(); String scheduleMonth = calV.getShowMonth(); Toast.makeText(mContext, scheduleYear + "-" + scheduleMonth + "-" + scheduleDay, Toast.LENGTH_SHORT).show(); } } }); gvCalendar.setLayoutParams(params); } private void setListener() { prevMonthIv.setOnClickListener(this); nextMonthIv.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.nextMonth: // 下一个月 enterNextMonth(); break; case R.id.prevMonth: // 上一个月 enterPrevMonth(); break; default: break; } } /** * 显示popWindow */ public void showPopupWindow(View parent) { if (!this.isShowing()) { // 以下拉方式显示popupwindow this.showAsDropDown(parent); } else { this.dismiss(); } } }

日历的内容是一个GridView,可以自定义类似签到效果的图标

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/bg_gray" > <TextView android:id="@+id/tv_text" android:layout_width="fill_parent" android:layout_height="30dp" android:gravity="center" /> <ImageView android:layout_width="15dp" android:layout_height="15dp" android:visibility="invisible" android:layout_alignParentBottom="true" android:background="@drawable/pen" android:layout_alignParentEnd="true" android:id="@+id/iv_pen" /> </RelativeLayout>

日历的adapter

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
public class CalendarAdapter extends BaseAdapter { private boolean isLeapYear = false; // 是否为闰年 private int daysOfMonth = 0; // 某月的天数 private int dayOfWeek = 0; // 具体某一天是星期几 private int lastDaysOfMonth = 0; // 上一个月的总天数 private Context context; private String[] dayNumber = new String[42]; // 一个gridview中的日期存入此数组中 private SpecialCalendar sc = null; private Resources res = null; private String currentYear = ""; private String currentMonth = ""; private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d"); private int currentFlag = -1; // 用于标记当天 private String showYear = ""; // 用于在头部显示的年份 private String showMonth = ""; // 用于在头部显示的月份 // 系统当前时间 private String sysDate = ""; private String sys_year = ""; private String sys_month = ""; private String sys_day = ""; public CalendarAdapter() { Date date = new Date(); sysDate = sdf.format(date); // 当期日期 sys_year = sysDate.split("-")[0]; sys_month = sysDate.split("-")[1]; sys_day = sysDate.split("-")[2]; } public CalendarAdapter(Context context, Resources rs, int jumpMonth, int jumpYear, int year_c, int month_c, int day_c) { this(); this.context = context; sc = new SpecialCalendar(); this.res = rs; int stepYear = year_c + jumpYear; int stepMonth = month_c + jumpMonth; if (stepMonth > 0) { // 往下一个月滑动 if (stepMonth % 12 == 0) { stepYear = year_c + stepMonth / 12 - 1; stepMonth = 12; } else { stepYear = year_c + stepMonth / 12; stepMonth = stepMonth % 12; } } else { // 往上一个月滑动 stepYear = year_c - 1 + stepMonth / 12; stepMonth = stepMonth % 12 + 12; if (stepMonth % 12 == 0) { } } currentYear = String.valueOf(stepYear); // 得到当前的年份 currentMonth = String.valueOf(stepMonth); // 得到本月 // (jumpMonth为滑动的次数,每滑动一次就增加一月或减一月) getCalendar(Integer.parseInt(currentYear), Integer.parseInt(currentMonth)); } @Override public int getCount() { // TODO Auto-generated method stub return dayNumber.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.calendar_item, null); } TextView textView = (TextView) convertView.findViewById(R.id.tv_text); ImageView ivPen = (ImageView) convertView.findViewById(R.id.iv_pen); String d = dayNumber[position]; SpannableString sp = new SpannableString(d); sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sp.setSpan(new RelativeSizeSpan(1.2f), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(sp); textView.setTextColor(Color.BLACK);// 字体设黑 if (position % 7 == 0 || position % 7 == 6) { // 当前月信息显示 textView.setTextColor(res.getColor(R.color.green));// 周末字体设绿色 } if (position >= dayOfWeek && position < daysOfMonth + dayOfWeek && (Integer.parseInt(sys_month) >= Integer.parseInt(currentMonth)&&Integer.parseInt(sys_year)==Integer.parseInt(currentYear) ||Integer.parseInt(sys_year)> Integer.parseInt(currentYear))) { // 当前月信息显示 int a[] = {2, 6, 29};//每个月不标记的天数 for (int i = 0; i < a.length; i++) { if (position == a[i]+dayOfWeek-1) { textView.setBackgroundColor(res.getColor(R.color.yellow));//为写日记日期填充黄色 ivPen.setVisibility(View.INVISIBLE); break; } else { ivPen.setVisibility(View.VISIBLE); } } } else if (position < dayOfWeek || position >= daysOfMonth + dayOfWeek) { textView.setTextColor(res.getColor(R.color.bg_gray)); } if (Integer.parseInt(sys_year)==Integer.parseInt(currentYear) &&Integer.parseInt(sys_month) == Integer.parseInt(currentMonth)&& currentFlag < position) { // 设置本月当天之后的背景 textView.setBackgroundColor(res.getColor(R.color.bg_gray));//全部填充灰色 ivPen.setVisibility(View.INVISIBLE); } if (currentFlag == position) { //设置当天的背景 textView.setBackgroundColor(res.getColor(R.color.blue)); textView.setTextColor(Color.WHITE); } return convertView; } // 得到某年的某月的天数且这月的第一天是星期几 public void getCalendar(int year, int month) { isLeapYear = sc.isLeapYear(year); // 是否为闰年 daysOfMonth = sc.getDaysOfMonth(isLeapYear, month); // 某月的总天数 dayOfWeek = sc.getWeekdayOfMonth(year, month); // 某月第一天为星期几 lastDaysOfMonth = sc.getDaysOfMonth(isLeapYear, month - 1); // 上一个月的总天数 getWeek(year, month); } // 将一个月中的每一天的值添加入数组dayNuber中 private void getWeek(int year, int month) { int j = 1; // 得到当前月的所有日程日期(这些日期需要标记) for (int i = 0; i < dayNumber.length; i++) { if (i < dayOfWeek) { // 前一个月 int temp = lastDaysOfMonth - dayOfWeek + 1; dayNumber[i] = (temp + i) + "" ; } else if (i < daysOfMonth + dayOfWeek) { // 本月 String day = String.valueOf(i - dayOfWeek + 1); // 得到的日期 dayNumber[i] = i - dayOfWeek + 1 + ""; // 对于当前月才去标记当前日期 if (sys_year.equals(String.valueOf(year)) && sys_month.equals(String.valueOf(month)) && sys_day.equals(day)) { // 标记当前日期 currentFlag = i; } setShowYear(String.valueOf(year)); setShowMonth(String.valueOf(month)); } else { // 下一个月 dayNumber[i] = j + ""; j++; } } } /** * 点击每一个item时返回item中的日期 * @param position * @return */ public String getDateByClickItem(int position) { return dayNumber[position]; } /** * 在点击gridView时,得到这个月中第一天的位置 * @return */ public int getStartPosition() { return dayOfWeek + 7; } /** * 在点击gridView时,得到这个月中最后一天的位置 * @return */ public int getEndPosition() { return (dayOfWeek + daysOfMonth + 7) - 1; } public String getShowYear() { return showYear; } public void setShowYear(String showYear) { this.showYear = showYear; } public String getShowMonth() { return showMonth; } public void setShowMonth(String showMonth) { this.showMonth = showMonth; } }

在MainActivity点击显示日历,可以指定PopWindow在哪一个控件的下方出现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopCalendar popCalendar = new PopCalendar(MainActivity.this); popCalendar.showPopupWindow(button); } }); } }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。

最后

以上就是纯情高跟鞋最近收集整理的关于Android实现可滑动的自定义日历控件的全部内容,更多相关Android实现可滑动内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(105)

评论列表共有 0 条评论

立即
投稿
返回
顶部