《移动项目实践》实验报告——Android高级控件
Posted Starzkg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《移动项目实践》实验报告——Android高级控件相关的知识,希望对你有一定的参考价值。
实验目的
1、熟悉App开发常用的一些高级控件及相关工具,主要包括日期时间控件的用法、列表类视图及其适配器的用法、翻页类视图及其适配器的用法、碎片及其适配器的用法等;
2、熟悉四大组件之一广播Broadcast的基本概念与常见用法;
实验内容
1、万年历:最简单的时间功能仅能查看当前的年月日、时分秒,若要拓展它的功能,则可由日历变月历,在年月日之外补充星期几,再添加节假日描述。进一步升级扩展,由月历变年历,分别按公历与农历纪年,便成了万年历;
万年历的界面效果
2、日程表(日程提醒采用手机震动的方式):日程表不但支持基本的日历信息展示,而且支持用户设定每天的日程安排,还支持日程提醒时间。
日程表的主页面
日程安排/详情页面
实验过程(实验的设计思路、关键源代码等)
源代码:https://gitee.com/shentuzhigang/mini-project/tree/master/android-calendar
package io.shentuzhigang.demo.calendar
import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.PagerTabStrip
import androidx.viewpager.widget.ViewPager
import io.shentuzhigang.demo.calendar.util.DateUtil
import io.shentuzhigang.demo.calendar.widget.MonthPicker
import io.shentuzhigang.demo.calendar.adapter.CalendarPagerAdapter
@SuppressLint("SetTextI18n")
class CalendarActivity : AppCompatActivity(), View.OnClickListener {
private var ll_calendar_main // 声明一个万年历区域的线性布局对象
: LinearLayout? = null
private var ll_month_select // 声明一个月份选择区域的线性布局对象
: LinearLayout? = null
private var mp_month // 声明一个月份选择器对象
: MonthPicker? = null
private var vp_calendar // 声明一个翻页视图对象
: ViewPager? = null
private var tv_calendar // 声明一个选中年份的文本视图对象
: TextView? = null
private var isShowSelect = false // 是否显示月份选择器
private var mSelectedYear = 2000 // 当前选中的年份
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_calendar)
ll_calendar_main = findViewById(R.id.ll_calendar_main)
ll_month_select = findViewById(R.id.ll_month_select)
// 从布局文件中获取名叫mp_month的月份选择器
mp_month = findViewById<MonthPicker>(R.id.mp_month)
// 从布局文件中获取名叫pts_calendar的翻页标题栏
findViewById<View>(R.id.btn_ok).setOnClickListener(this)
val pts_calendar = findViewById<PagerTabStrip>(R.id.pts_calendar)
pts_calendar.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17f)
pts_calendar.setTextColor(Color.BLACK)
// 从布局文件中获取名叫vp_calendar的翻页视图
vp_calendar = findViewById(R.id.vp_calendar)
tv_calendar = findViewById(R.id.tv_calendar)
with(tv_calendar){
this?.setOnClickListener(this@CalendarActivity)
}
// 万年历默认显示当前年月的月历
showCalendar(DateUtil.nowYear, DateUtil.nowMonth)
}
// 显示指定年月的万年历
private fun showCalendar(year: Int, month: Int) {
// 如果指定年份不是上次选中的年份,则需重新构建该年份的年历
if (year != mSelectedYear) {
tv_calendar!!.text = year.toString() + "年"
// 构建一个指定年份的年历翻页适配器
val adapter = CalendarPagerAdapter(supportFragmentManager, year)
// 给vp_calendar设置年历翻页适配器
vp_calendar!!.adapter = adapter
mSelectedYear = year
}
// 设置vp_calendar默认显示指定月份的月历页
vp_calendar!!.currentItem = month - 1
}
override fun onClick(v: View) {
if (v.id == R.id.tv_calendar) { // 点击了年份文本
// 重新选择万年历的年月
resetPage()
} else if (v.id == R.id.btn_ok) { // 点击了确定按钮
// 根据月份选择器上设定的年月,刷新万年历的显示界面
showCalendar(mp_month!!.getYear(), mp_month!!.getMonth() + 1)
resetPage()
}
}
// 重置页面。在显示万年历主页面和显示月份选择器之间切换
private fun resetPage() {
isShowSelect = !isShowSelect
ll_calendar_main!!.visibility = if (isShowSelect) View.GONE else View.VISIBLE
ll_month_select!!.visibility = if (isShowSelect) View.VISIBLE else View.GONE
}
companion object {
private const val TAG = "CalendarActivity"
}
}
package io.shentuzhigang.demo.calendar
import android.content.*
import android.graphics.Color
import android.os.*
import android.util.Log
import android.util.TypedValue
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.viewpager.widget.PagerTabStrip
import androidx.viewpager.widget.ViewPager
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import io.shentuzhigang.demo.calendar.adapter.SchedulePagerAdapter
import io.shentuzhigang.demo.calendar.calendar.SpecialCalendar
import io.shentuzhigang.demo.calendar.util.DateUtil
class ScheduleActivity : AppCompatActivity() {
private var ll_schedule // 声明一个日程表区域的线性布局对象
: LinearLayout? = null
private var vp_schedule // 声明一个翻页视图对象
: ViewPager? = null
private var mSelectedWeek // 当前选中的星期
= 0
private var mFestivalResid = 0 // 节日图片的资源编号
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_schedule)
// 从布局文件中获取名叫pts_schedule的翻页标题栏
val pts_schedule = findViewById<PagerTabStrip>(R.id.pts_schedule)
pts_schedule.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17f)
pts_schedule.setTextColor(Color.BLACK)
ll_schedule = findViewById(R.id.ll_schedule)
// 从布局文件中获取名叫vp_schedule的翻页视图
vp_schedule = findViewById(R.id.vp_schedule)
val tv_schedule = findViewById<TextView>(R.id.tv_schedule)
tv_schedule.setText(DateUtil.nowYearCN + " 日程安排")
// 获取今天所处的星期在一年当中的序号
mSelectedWeek = SpecialCalendar.todayWeek
// 构建一个日程表的翻页适配器
val adapter = SchedulePagerAdapter(supportFragmentManager)
// 给vp_schedule设置日程表翻页适配器
with(vp_schedule) {
// 给vp_schedule设置日程表翻页适配器
this?.setAdapter(adapter)
// 设置vp_schedule默认显示当前周数的日程页
this?.setCurrentItem(mSelectedWeek - 1)
// 给vp_schedule添加页面变化监听器
this?.addOnPageChangeListener(SheduleChangeListener())
}
// 延迟50毫秒再执行任务mFirst
mHandler.postDelayed(mFirst, 50)
}
private val mHandler = Handler() // 声明一个处理器对象
// 声明一个首次打开页面需要延迟执行的任务
private val mFirst = Runnable {
sendBroadcast(mSelectedWeek) // 发送广播,表示当前是在第几个星期
}
// 发送当前周数的广播
private fun sendBroadcast(week: Int) {
// 创建一个广播事件的意图
val intent = Intent(ACTION_FRAGMENT_SELECTED)
intent.putExtra(EXTRA_SELECTED_WEEK, week)
// 通过本地的广播管理器来发送广播
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
public override fun onStart() {
super.onStart()
// 创建一个节日图片的广播接收器
festivalReceiver = FestivalControlReceiver()
// 注册广播接收器,注册之后才能正常接收广播
LocalBroadcastManager.getInstance(this)
.registerReceiver(festivalReceiver!!, IntentFilter(ACTION_SHOW_FESTIVAL))
}
public override fun onStop() {
super.onStop()
// 注销广播接收器,注销之后就不再接收广播
LocalBroadcastManager.getInstance(this).unregisterReceiver(festivalReceiver!!)
}
override fun onResume() {
super.onResume()
if (mFestivalResid != 0) { // 在横屏和竖屏之间翻转时,不会重新onCreate,只会onResume
ll_schedule!!.setBackgroundResource(mFestivalResid)
}
}
// 声明一个节日图片的广播接收器
private var festivalReceiver: FestivalControlReceiver? = null
// 定义一个广播接收器,用于处理节日图片事件
private inner class FestivalControlReceiver : BroadcastReceiver() {
// 一旦接收到节日图片的广播,马上触发接收器的onReceive方法
override fun onReceive(context: Context, intent: Intent) {
if (intent != null) {
// 从广播消息中取出节日图片的资源编号
mFestivalResid = intent.getIntExtra(EXTRA_FESTIVAL_RES, 1)
// 把页面背景设置为广播发来的节日图片
ll_schedule!!.setBackgroundResource(mFestivalResid)
}
}
}
// 定义一个页面变化监听器,用于处理翻页视图的翻页事件
inner class SheduleChangeListener : OnPageChangeListener {
// 在翻页结束后触发
override fun onPageSelected(position: Int) {
Log.d(TAG, "onPageSelected position=$position, mSelectedWeek=$mSelectedWeek")
mSelectedWeek = position + 1
sendBroadcast(mSelectedWeek)
}
// 在翻页过程中触发
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
// 翻页状态改变时触发
override fun onPageScrollStateChanged(arg0: Int) {}
}
companion object {
private const val TAG = "ScheduleActivity"
// 声明一个碎片选中事件的标识串
var ACTION_FRAGMENT_SELECTED = "io.shentuzhigang.demo.calendar.ACTION_FRAGMENT_SELECTED"
// 声明一个选择星期参数的标识串
var EXTRA_SELECTED_WEEK = "selected_week"
// 声明一个显示节日事件的标识串
var ACTION_SHOW_FESTIVAL = "io.shentuzhigang.demo.calendar.ACTION_SHOW_FESTIVAL"
// 声明一个节日图片参数的标识串
var EXTRA_FESTIVAL_RES = "festival_res"
}
}
实验结果(实验最终作品截图说明)
实验心得
1、熟悉App开发常用的一些高级控件及相关工具,主要包括日期时间控件的用法、列表类视图及其适配器的用法、翻页类视图及其适配器的用法、碎片及其适配器的用法等;
2、熟悉四大组件之一广播Broadcast的基本概念与常见用法;
参考项目
参考文章
以上是关于《移动项目实践》实验报告——Android高级控件的主要内容,如果未能解决你的问题,请参考以下文章