├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── dbnavigator.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ ├── demo.apk │ └── output-metadata.json └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── calendar │ │ └── app │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── calendar │ │ │ └── app │ │ │ ├── MainActivity.kt │ │ │ ├── MultiActivity.kt │ │ │ ├── RangeActivity.kt │ │ │ ├── SimpleActivity.kt │ │ │ ├── SingleActivity.kt │ │ │ ├── StyleActivity.kt │ │ │ ├── WeekActivity.kt │ │ │ └── view │ │ │ └── CustomHeaderView.kt │ └── res │ │ ├── color │ │ └── btn_selector.xml │ │ ├── drawable │ │ ├── arrow_down.png │ │ ├── arrow_up.png │ │ ├── bg.xml │ │ ├── default_header_bg.xml │ │ ├── header_bg.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_multi.xml │ │ ├── activity_range.xml │ │ ├── activity_single.xml │ │ ├── activity_style.xml │ │ ├── activity_week.xml │ │ └── header_view.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── calendar │ └── app │ └── ExampleUnitTest.kt ├── build.gradle ├── demo └── demo.apk ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── calendar │ │ └── library │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── hdev │ │ │ └── calendar │ │ │ ├── adapter │ │ │ └── CalendarAdapter.kt │ │ │ ├── base │ │ │ ├── BaseCalendarView.kt │ │ │ ├── BaseHeaderView.kt │ │ │ ├── BaseMonthView.kt │ │ │ └── BaseWeekView.kt │ │ │ ├── bean │ │ │ ├── ClickableType.kt │ │ │ ├── DateInfo.kt │ │ │ ├── DateItem.kt │ │ │ ├── RangeViewAttrs.kt │ │ │ └── ViewAttrs.kt │ │ │ ├── constant │ │ │ └── Const.kt │ │ │ ├── listener │ │ │ ├── DateListener.kt │ │ │ ├── IDateRange.kt │ │ │ └── OnDateSelectedListener.kt │ │ │ ├── util │ │ │ ├── DateUtil.kt │ │ │ └── Util.kt │ │ │ └── view │ │ │ ├── DefaultHeaderView.kt │ │ │ ├── DefaultRangeHeaderView.kt │ │ │ ├── MultiCalendarView.kt │ │ │ ├── RangeCalendarView.kt │ │ │ ├── SingleCalendarView.kt │ │ │ ├── WeekCalendarView.kt │ │ │ ├── WeekTitleView.kt │ │ │ └── month │ │ │ ├── MultiMonthView.kt │ │ │ ├── RangeMonthView.kt │ │ │ ├── SingleMonthView.kt │ │ │ └── WeekMonthView.kt │ └── res │ │ ├── drawable │ │ └── default_header_bg.xml │ │ ├── layout │ │ ├── default_header_view.xml │ │ └── default_range_header_view.xml │ │ └── values │ │ ├── calendar_attrs.xml │ │ └── ids.xml │ └── test │ └── java │ └── com │ └── calendar │ └── library │ └── ExampleUnitTest.kt ├── preview ├── multi.gif ├── range.gif ├── single.gif ├── style.gif └── week.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 hdev0225 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## CalendarView 日历控件 2 | ### Calendar View 使用kotlin语言开发,支持单选,多选,按星期选,跨月份日期范围选择,样式设置 3 | ### 设置不可选择日期,设置只可选择某些日期 4 | 5 | ## 运行环境 6 | > AS 版本: Android Studio Dolphin | 2021.3.1 7 | 8 | > Android Gradle Plugin Version: 7.3.0 9 | 10 | > Gradle Version: 7.5 11 | 12 | ## 示例 13 | [Demo](https://github.com/hdev0225/CalendarView/blob/master/demo/demo.apk) 14 | 15 | ## 安装 16 | > 1、添加JitPack仓库到根路径下的build.gradle 17 | ```java 18 | allprojects { 19 | repositories { 20 | // ... 21 | maven { url 'https://jitpack.io' } 22 | } 23 | } 24 | ``` 25 | > 2、添加依赖到模块中的build.gradle 26 | ```java 27 | dependencies { 28 | implementation 'com.github.hdev0225:CalendarView:v1.0.6' 29 | } 30 | ``` 31 | 32 | ## 日历功能简介 33 | ##### [简单应用](#简单示例) 34 | ##### [单选日历](#单选) 35 | ##### [多选日历](#多选) 36 | ##### [按星期选择日历](#按星期选择) 37 | ##### [日期范围选择](#按日期范围选择) 38 | ##### [设置样式](#设置日历样式) 39 | ##### [设置不可选择日期列表](#设置不可选择日期) 40 | ##### [设置只可选择某些日期列表](#设置只可选择某些日期) 41 | 42 | ### 简单示例 43 | > 默认情况下:开始日期为1970-1-1,结束日期为手机时间,并选中当前时间 44 | ```xml 45 | 51 | ``` 52 | 53 | ### 单选 54 | ![image](https://github.com/hdev0225/CalendarView/blob/master/preview/single.gif) 55 | 56 | ```xml 57 | 63 | ``` 64 | 65 | ```java 66 | val calendarView: SingleCalendarView = findViewById(R.id.calendar_view) 67 | // 事件监听 68 | calendarView.setOnSingleDateSelectedListener { 69 | _, dateInfo -> 70 | Toast.makeText(this@SingleActivity, dateInfo.toString(), Toast.LENGTH_LONG).show()} 71 | // 开始日期 72 | var startDate = DateInfo(2023, 1, 15) 73 | // 结束日期 74 | val endDate = DateInfo(2023, 4, 15) 75 | // 选中2023-1-1 76 | val selectedDate = DateInfo(2023, 1, 1) 77 | // 初始化,设置日期范围 78 | calendarView.setDateRange( 79 | startDate.timeInMillis(), 80 | endDate.timeInMillis(), 81 | selectedDate.timeInMillis() 82 | ) 83 | ``` 84 | 85 | ### 多选 86 | ![image](https://github.com/hdev0225/CalendarView/blob/master/preview/multi.gif) 87 | ```xml 88 | 95 | 96 | ``` 97 | ```java 98 | val dateList = mutableListOf() 99 | dateList.add(DateInfo(2023, 5, 3)) 100 | dateList.add(DateInfo(2023, 5, 8)) 101 | dateList.add(DateInfo(2023, 5, 5)) 102 | 103 | val calendarView: MultiCalendarView = findViewById(R.id.calendar_view) 104 | calendarView.setOnMultiDateSelectedListener { 105 | _, clickedDate, dateList -> 106 | } 107 | // 设置选中日期列表 108 | calendarView.selectedDateList = dateList 109 | ``` 110 | 111 | ### 按星期选择 112 | ![image](https://github.com/hdev0225/CalendarView/blob/master/preview/week.gif) 113 | 114 | ```xml 115 | 121 | ``` 122 | 123 | ```java 124 | // 开始日期 125 | val startDate = DateInfo(2021, 12, 30) 126 | // 结束日期 127 | val endDate = DateInfo(2023, 4, 15) 128 | // 设置某一天,该星期会选中 129 | val selectedDate = DateInfo(2022, 1, 1) 130 | 131 | val calendarView: WeekCalendarView = findViewById(R.id.calendar_view) 132 | // 事件监听 133 | calendarView.setOnDateRangeSelectedListener { 134 | _, selecteDate, startDate, endDate -> 135 | Toast.makeText(this@WeekActivity, "start: $startDate, end:$endDate", Toast.LENGTH_LONG).show() 136 | } 137 | ``` 138 | 139 | ### 按日期范围选择 140 | ![image](https://github.com/hdev0225/CalendarView/blob/master/preview/range.gif) 141 | ```xml 142 | 157 | ``` 158 | 159 | ```java 160 | val calendarView: RangeCalendarView = findViewById(R.id.calendar_view) 161 | // 设置日期范围 162 | calendarView.setSelectedDateRange(DateInfo(2023, 2, 21), DateInfo(2023, 5, 13)) 163 | // 事件监听 164 | calendarView.setOnDateRangeSelectedListener { 165 | _, // 日历控件 166 | _, // 选中的日期 167 | startDate: DateInfo, // 开始日期 168 | endDate: DateInfo -> // 结束日期 169 | Toast.makeText(this@RangeActivity, "${startDate.format()}---${endDate.format()}", Toast.LENGTH_SHORT).show() 170 | } 171 | ``` 172 | 173 | ### 设置日历样式 174 | ![image](https://github.com/hdev0225/CalendarView/blob/master/preview/style.gif) 175 | 176 | ```xml 177 | 195 | ``` 196 | #### 通用属性 197 | > header_view:头部,包名+类型,需要继承BaseHeaderView类,自定义头部 198 | 199 | > day_font_size:日期字体大小,eg: 16sp 200 | 201 | > week_title_color: 星期标题颜色,类型:颜色码或者颜色引用, eg:#ffff00或者R.color.red; 202 | 203 | > week_title_font_size:星期标题字体大小, eg: 12sp; 204 | 205 | > week_title_label:星期标题,以顿号分割,如:一、二、三、四、五、六、日。起始星期为星期一; 206 | 207 | ##### 注!!!:设置了first_day_of_week,需要同时设置week_title_label 208 | > first_day_of_week:一周的第一天,1表示星期一,2表示星期二,7表示星期天; 209 | 210 | > default_color:默认文字颜色,类型:颜色码或者颜色引用, eg:#ffff00或者R.color.red; 211 | 212 | > default_dim_color:默认文字灰色,类型:颜色码或者颜色引用, eg:#ffff00或者R.color.red; 213 | 214 | > weekend_color:周未字体颜色,类型:颜色码或者颜色引用, eg:#ffff00或者R.color.red; 215 | 216 | > selected_bg_color:选中背景色,类型:颜色码或者颜色引用, eg:#ffff00或者R.color.red; 217 | 218 | > selected_day_color:选中日子颜色,类型:颜色码或者颜色引用, eg:#ffff00或者R.color.red; 219 | 220 | > selected_day_dim_color:范围选择或者按星期选择的日历时,该日期不能选择,但在范围或者星期之间, eg:#ffff00或者R.color.red; 221 | 222 | #### 日期范围属性 223 | > selected_range_bg_color:选中区间背景色,开始与结束之间的日期(不包括开始和结束日期), eg:#ffff00或者R.color.red; 224 | 225 | > selected_range_day_color:选中区间字体颜色,开始与结束之间的日期(不包括开始和结束日期), eg:#ffff00或者R.color.red; 226 | 227 | > selected_start_bg_color:开始日期背景色, eg:#ffff00或者R.color.red; 228 | 229 | > selected_start_day_color:开始日期字体颜色, eg:#ffff00或者R.color.red; 230 | 231 | > selected_end_bg_color:结束日期背景色, eg:#ffff00或者R.color.red; 232 | 233 | > selected_end_day_color:结束日期字体颜色, eg:#ffff00或者R.color.red; 234 | 235 | ### 设置不可选择日期 236 | ```java 237 | val dateList = mutableListOf() 238 | dateList.add(DateInfo(2023, 4, 8)) 239 | dateList.add(DateInfo(2023, 4, 11)) 240 | dateList.add(DateInfo(2023, 3, 31)) 241 | val calendarView: WeekCalendarView = findViewById(R.id.calendar_view) 242 | // setup un-clickable date 243 | calendarView.unClickableDateList = dateList 244 | ``` 245 | ### 设置只可选择某些日期 246 | ```java 247 | val dateList = mutableListOf() 248 | dateList.add(DateInfo(2023, 4, 8)) 249 | dateList.add(DateInfo(2023, 4, 11)) 250 | dateList.add(DateInfo(2023, 3, 31)) 251 | val calendarView: WeekCalendarView = findViewById(R.id.calendar_view) 252 | calendarView.clickableDateList = dateList 253 | ``` 254 | 255 | ## CalendarView方法说明 256 | #### 通用方法 257 | > unClickableDateList 设置不可点击的日期列表 258 | 259 | > clickableDateList 设置只能点击的日期列表 260 | 261 | > setDateRange 设置日期范围,参数:开始日期,结束日期,当前选中的日期 262 | 263 | #### 单先日历 264 | > setSelectedDate 设置选中某一天,如:点击按钮后,跳转到某一个日期 265 | 266 | #### 多选日历 267 | > selectedDateList 设置选中的日期列表/获取选中的日期列表 268 | 269 | #### 事件监听 270 | ```java 271 | /** 272 | * 单选接口回调 273 | */ 274 | OnSingleDateSelectedListener( 275 | view: SingleCalendarView, // 日历控件 276 | selectedDate: DateInfo // 选中的日期 277 | ) 278 | 279 | /** 280 | * 按星期选,区域选择接口回调 281 | */ 282 | OnDateRangeSelectedListener( 283 | view: BaseCalendarView, // 日历控件 284 | selectedDate: DateInfo, // 选中的日期 285 | startDate: DateInfo, // 开始日期 286 | endDate: DateInfo // 结束日期 287 | ) 288 | 289 | /** 290 | * 多选 291 | */ 292 | OnMultiDateSelectedListener( 293 | view: MultiCalendarView, // 日历控件 294 | clickedDate: DateInfo, // 当前当点的日期,选中或者取消选中 295 | dateList: List, // 日期列表 296 | ) 297 | ``` 298 | 299 | ## DateInfo类说明 300 | > 提供将dateInfo转calendar 301 | 302 | > 将calendar转成dateInfo 303 | 304 | > 将dateInfo转毫秒 305 | 306 | 307 | ## BaseHeaderView说明 308 | > 自定义头部,需要继承BaseHeaderView,更新标题,显示或者隐藏上下面,然后在xml布局文件中设置header_view,如下 309 | ```xml 310 | app:header_view="com.calendar.app.view.CustomHeaderView" 311 | ``` 312 | 313 | ```java 314 | /** 315 | * 获取布局id,如:R.layout.default_header_view 316 | */ 317 | protected abstract fun getLayoutId(): Int 318 | 319 | /** 320 | * 更新标题 321 | */ 322 | open fun updateTitle(year: Int, month: Int) {} 323 | 324 | /** 325 | * 处理上、下按钮 326 | * @param hasPrev 是否有上一页 327 | * @param hasNext 是否有下一页 328 | */ 329 | open fun handlePrevNext(hasPrev: Boolean, hasNext: Boolean) {} 330 | ``` 331 | 332 | ## IDateRange 接口说明 333 | > 日期范围选择RangeCalendarView,如果自定义headerView实现该接口,可更新headerView日期范围,可参考DefaultRangeHeaderView类 334 | ```java 335 | class DefaultRangeHeaderView( 336 | context: Context 337 | ) : DefaultHeaderView(context), IDateRange { 338 | 339 | private lateinit var dateRangeLabel: TextView 340 | 341 | override fun dateRange(startDate: DateInfo?, endDate: DateInfo?) { 342 | if (startDate == null && endDate == null) { 343 | dateRangeLabel.text = "" 344 | } else if (startDate != null && endDate != null) { 345 | dateRangeLabel.text = "${startDate.format()} -- ${endDate.format()}" 346 | } else if (startDate != null) { 347 | dateRangeLabel.text = startDate.format() 348 | } 349 | } 350 | 351 | override fun getLayoutId(): Int { 352 | return R.layout.default_range_header_view 353 | } 354 | 355 | override fun init() { 356 | super.init() 357 | dateRangeLabel = findViewById(R.id.date_range_label) 358 | } 359 | } 360 | ``` 361 | 362 | 363 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | namespace 'com.calendar.app' 8 | compileSdk 33 9 | 10 | defaultConfig { 11 | applicationId "com.calendar.app" 12 | minSdk 21 13 | targetSdk 33 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | compileOptions { 27 | sourceCompatibility JavaVersion.VERSION_1_8 28 | targetCompatibility JavaVersion.VERSION_1_8 29 | } 30 | kotlinOptions { 31 | jvmTarget = '1.8' 32 | } 33 | } 34 | 35 | dependencies { 36 | 37 | implementation 'androidx.core:core-ktx:1.7.0' 38 | implementation 'androidx.appcompat:appcompat:1.6.1' 39 | implementation 'com.google.android.material:material:1.8.0' 40 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 41 | implementation project(path: ':library') 42 | testImplementation 'junit:junit:4.13.2' 43 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 44 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 45 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/release/demo.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hdev0225/CalendarView/de7b0a6c9f2ef2f537e2d63b253ff40e4fa8bfb8/app/release/demo.apk -------------------------------------------------------------------------------- /app/release/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "com.calendar.app", 8 | "variantName": "release", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "attributes": [], 14 | "versionCode": 1, 15 | "versionName": "1.0", 16 | "outputFile": "app-release.apk" 17 | } 18 | ], 19 | "elementType": "File" 20 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/calendar/app/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.calendar.app 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.calendar.app", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/calendar/app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.calendar.app 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.widget.Button 6 | import androidx.appcompat.app.AppCompatActivity 7 | 8 | /** 9 | * Created by han on 2023/4/6. 10 | */ 11 | class MainActivity : AppCompatActivity() { 12 | 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | setContentView(R.layout.activity_main) 16 | 17 | findViewById