一个简单的闹钟

  • 效果视频
    • 闹钟子项
      • 子项布局效果图
      • 闹钟适配器类
      • 闹钟初始数据
      • 侧滑删除闹钟子项
        • 添加依赖
        • 布局设置
        • 实现侧滑回调方法
        • 绑定RecyclerView
        • 删除子项
      • 新增闹钟子项
        • 序列化实体类
          • 定义实体类,并实现序列化
          • 取出序列化实体类对象
        • TimePicker
          • 自定义TimePicker文字大小及颜色
          • 获取时间数据
          • 返回时间数据
          • 存储数据
            • 取出数据
            • 子项添加
    • 自定义Switch样式
      • Switch效果如图
      • 创建`thumb`和`track`样式
        • thumb样式
          • 选中状态
          • 默认状态
        • track样式
          • 选中状态
          • 默认状态
    • 闹钟提醒服务
      • Service
      • 开始服务
      • 暂停服务
    • 单例类
      • SP封装类
      • KillProcess封装类
      • TimeFormat封装类
  • 下载地址
  • 尾言

效果视频

闹钟子项

子项布局效果图

闹钟适配器类

本示例采用的是RecyclerView,其适配器类与常无二,其异在于继承一个代理类,为适配之后侧滑删除而准备

public class ClockAdapter extends WeSwipeProxyAdapter<ClockAdapter.ViewHolder>

建立一个内部类ViewHolder实现控件定义申明

public ViewHolder(@NonNull View itemView) {super( itemView );DeleteBtn = itemView.findViewById( R.id.DeleteBtn );Hour = itemView.findViewById( R.id.Hour );Split = itemView.findViewById( R.id.Split );Min = itemView.findViewById( R.id.Min );Layout = itemView.findViewById( R.id.ItemLayout );ClockSwitch = itemView.findViewById( R.id.ClockSwitch );}

实现onCreateViewHolder方法载入子项布局文件

public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from( parent.getContext() ).inflate( R.layout.clock_item,parent,false );return new ViewHolder( view );}

绑定实体类,实现onBindViewHolder获取数据

public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {final ClockTime clockTime = timeList.get( position );holder.Hour.setText( clockTime.getHour() );holder.Split.setText( ":" );holder.Min.setText( clockTime.getMin() );boolean isSelect = clockTime.isSelect();if (isSelect){holder.ClockSwitch.setChecked( true );}else {holder.ClockSwitch.setChecked( false );}holder.DeleteBtn.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v) {DeleteItem(position);}} );holder.ClockSwitch.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (isChecked){SelectModel(holder,clockTime);}else {NormalModel(holder);}}} );}

闹钟初始数据

此处有三处状态,第一种状态:第一次进入程序,默认加载固定闹钟子项;第二种状态:进入添加子项页面,然后返回其主页面,并判断其switch是否为ture,如果为ture则添加子项;第三种状态:程序被系统回收或者用户停止程序,并再次进入程序,防止加载前一时刻闹钟子项;

    /*** 默认数据*/private void InitData(){if (flag == START){for (int i = 6; i < 20 ; i+=2) {ClockTime clockTime = new ClockTime( timeFormat.HandleHour( i ),timeFormat.HandleHour( i ),false );clockTimeList.add( clockTime );clockTime.setClockTimeList( clockTimeList );}}else if (flag == PAUSE){GetCallBackData();}else {Log.d( TAG,"Restart App" );}}

侧滑删除闹钟子项

添加依赖

实现侧滑主要依赖于一个第三方包,然后使用RecyclerView进行子项绑定
依赖如下:

    implementation 'com.github.WangcWj:WeSwipe:1.0.2'implementation 'cn.wang.we:network:1.0.0'

并在目录build.gradle包下添加如下库

 maven { url 'https://jitpack.io' }

布局设置

其实现侧滑删除主要的玄机在于布局文件当中,使用RelativeLayout布局,将删除按钮固定在布局右方,并使用其他布局将其覆盖,只有滑动时,才将其显示。掩盖侧滑删除按钮与暴露侧滑删除按钮效果对比图如下

实现侧滑回调方法

然后,在适配器类中,实现WeSwipeHelper.SwipeLayoutTypeCallBack接口,实现如下三个方法,第一个方法为获取侧滑删除按钮的宽度;第二个方法为需要滑动的视图,也就是覆盖侧滑删除按钮的布局;第三个方法为当视图正在滑动时,用户触发单击事件,自动还原滑动状态

        float getSwipeWidth();//获取侧滑删除按钮的宽度View needSwipeLayout();View onScreenView();

绑定RecyclerView

最后,在需要添加子项的视图中绑定RecyclerView即可

WeSwipe.attach( mRecyclerView );

删除子项

通过监听子项滑动删除按钮点击事件,实现子项删除

 holder.DeleteBtn.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View v) {DeleteItem(position);}} );
  private void DeleteItem(int position){timeList.remove( position );notifyDataSetChanged();}

新增闹钟子项

序列化实体类

跳转新增闹钟子项Acticity需要传输实体类对象,传输对象一般需要序列化改类,其操作如下

定义实体类,并实现序列化
public class ClockTime implements Serializable

然后通过Intent传输Bundle对象

 public void Add(View view){flag = 1;Intent intent = new Intent( context,AddClockActivity.class );Bundle bundle = new Bundle(  );bundle.putSerializable( "list",(Serializable)clockTimeList );intent.putExtras( bundle );startActivity( intent );}
取出序列化实体类对象
 clockTimeList = (List<ClockTime>) getIntent().getSerializableExtra( "list" );

TimePicker

实现时间选择主要使用系统集成的组件TimePicker,其使用方法如下
其有两种显示方式,第一种为spinner,就是下拉滑动式,第二种为clock,即显示一个时钟,通过滑动指针选择时间

 <TimePickerandroid:id="@+id/TimePicker"android:layout_width="wrap_content"android:layout_height="wrap_content"android:timePickerMode="spinner"/>
自定义TimePicker文字大小及颜色

在style.xml文件中申明如下样式

   <style name="ThemePicker" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:editTextStyle">@style/Widget.Picker.Style</item></style><style name="Widget.Picker.Style" parent="@android:style/Widget.EditText"><item name="android:textColor">@color/colorWhite</item><item name="android:textSize">15sp</item></style>

然后再指定Activcty申明即可

 <activityandroid:name=".view.AddClockActivity"android:theme="@style/ThemePicker"></activity><activity
获取时间数据

获取数据比较简单,实现对应接口即可

timePicker.setOnTimeChangedListener( new TimePicker.OnTimeChangedListener() {@Overridepublic void onTimeChanged(TimePicker view, int hourOfDay, int minute) {mHour = hourOfDay;mMin = minute;}} );
返回时间数据

将获取的数据通过SharedPreferences存储起来,然后点击存储时,进行页面跳转,然后再该界面进行取出数据

存储数据
       sp.PutData( context, "Hour", mHour );sp.PutData( context, "Min", mMin );sp.PutData( context, "isSelect", isSelect );
取出数据

首先判断回调的switch数据是否为ture,如果为ture则保存该子项,然后再适配器类中进行数据添加

boolean access = (Boolean) sp.GetData( context,"access",false );if (access) {int Hour = (int) sp.GetData( context, "Hour", 0 );int Min = (int) sp.GetData( context, "Min", 0 );boolean isSelect = (boolean) sp.GetData( context, "isSelect", false );Log.d( TAG, Hour + "firstHour" );Log.d( TAG, Min + "firstMin" );if (Hour == 0 || Min == 0) {Log.d( TAG, "null" );} else {clockTime = new ClockTime( timeFormat.HandleHour( Hour ), timeFormat.HandleHour( Min ), isSelect );adapter.AddItem( clockTime );}}else {Log.d( TAG,"Cancel Set AlarmClock" );}
子项添加
public void AddItem(ClockTime clockTime){timeList.add( clockTime );notifyDataSetChanged();}

自定义Switch样式

Switch效果如图

选中与默认两种状态效果图如下

创建thumbtrack样式

thumb样式

创建一个选择器文件,有选中和默认两种状态

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/open_thumb"/>
<item android:drawable="@drawable/shut_thumb"/>
</selector>
选中状态

创新open_thumb.xml文件

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- 高度40 -->
<size android:height="20dp" android:width="20dp"/>
<!-- 圆角弧度 20 -->
<corners android:radius="10dp"/>
<!-- 变化率 -->
<gradientandroid:endColor="#eeeeee"android:startColor="#eeeeee" />
<stroke android:width="1dp"android:color="#33da33"/>
</shape>
默认状态

创建shut_thumb.xml文件

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle" >
<size android:height="20dp" android:width="20dp"/>
<!-- 圆角弧度 20 -->
<corners android:radius="10dp"/>
<!-- 变化率 -->
<gradientandroid:endColor="#eeeeee"android:startColor="#eeeeee" />
<stroke android:width="1dp"android:color="#666666"/></shape>

track样式

同样创建一个选择器,并用于两种状态

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_checked="true" android:drawable="@drawable/open_track"/><item android:drawable="@drawable/shut_track"/>
</selector>
选中状态
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"><!-- 高度30   此处设置宽度无效--><size android:height="20dp"/><!-- 圆角弧度 15 --><corners android:radius="10dp"/><!-- 变化率  定义从左到右的颜色不变 --><gradientandroid:endColor="#2EA803"android:startColor="#2EA803" />
</shape>
默认状态
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><size android:height="20dp" android:width="20dp"/><corners android:radius="10dp"/><gradient android:startColor="#eeeeee"android:endColor="#eeeeee"/><stroke android:width="1dp"android:color="#666666"/>
</shape>

闹钟提醒服务

Service

创建一个服务类
其中AlarmManager为系统主要操作类,参数为提醒模式、提醒时间(long型)、PendingIntent对象
以下有三种时间传入,第一种,直接传入一个Long型时间用于测试,第二种,通过设置系统启动至今而设置时间,第三种,通过取出设置的时间,然后获取系统当前时间,将其差传入其中。

public class ClockService extends Service {private Intent intent;private PendingIntent pendingIntent;private AlarmManager alarmManager;private int Hour,Min;private Calendar calendar;@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);calendar = Calendar.getInstance();/*** 10秒,用于测试*/long Minutes = 60*1000*60;//long triggerAtTime = SystemClock.elapsedRealtime() + Minutes;//alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);/*** 理论*/Hour = intent.getIntExtra("Hour",0);Min = intent.getIntExtra("Min",0);Log.d( TAG,Hour+"ClockServiceHour" );Log.d( TAG,Min+"ClockServiceMin" );calendar.setTimeZone( TimeZone.getTimeZone( "GMT+8:00" ) );calendar.set( Calendar.HOUR_OF_DAY, Hour );calendar.set( Calendar.MINUTE, Min );long clockTime = calendar.getTimeInMillis();long current = System.currentTimeMillis();long time = clockTime - current;Log.d( TAG,clockTime+"Clock" );Log.d( TAG,current+"Current" );Log.d( TAG,time+"Millisecond" );intent = new Intent(this, WarnActivity.class);pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);alarmManager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);return super.onStartCommand( intent, flags, startId );}@Overridepublic void onDestroy() {super.onDestroy();//alarmManager.cancel(pendingIntent);}
}

然后再清单文件中注册服务

 <service android:name=".service.ClockService"android:theme="@style/NotTitleBar"/>

开始服务

使用Intent实现服务启动

  private void StartService(){Intent intent = new Intent( this, ClockService.class );intent.putExtra( "Hour",mHour );intent.putExtra( "Min",mMin );startService( intent );}

暂停服务

杀死程序

public void Exit(View view){killProcess.finishAll();}

单例类

本示例总共使用到了三个单例类:SP(SharedPreferences封装)、TimeFormat(时间数据格式封装)、KillProcess(杀死所有Activity)

SP封装类

SharedPreferences

KillProcess封装类

KillProcess

TimeFormat封装类

ublic class TimeFormat {private static TimeFormat timeFormat;private TimeFormat(){}public static TimeFormat getInstance(){if (timeFormat == null){sync();}return timeFormat;}private static synchronized void sync(){if (timeFormat == null){timeFormat = new TimeFormat();}}public String HandleHour(int hour){if (hour < 10){return "0"+hour;}else {return String.valueOf( hour );}}public String HandleWeek(int week){String weekday = "";switch (week){case 1:weekday = "星期一";break;case 2:weekday = "星期二";break;case 3:weekday = "星期三";break;case 4:weekday = "星期四";break;case 5:weekday = "星期五";break;case 6:weekday = "星期六";break;case 7:weekday = "星期七";break;}return weekday;}
}

下载地址

Gitee下载地址

尾言

目前项目仍存在很多问题,有时间会继续进行迭代

Android——一个简单的闹钟APP相关推荐

  1. 用Android Studio设计的一个简单的闹钟APP

    该闹钟是用Android Studio为安卓手机设计的一个简单的闹钟APP 一.介绍系统的设计界面 闹钟的布局文件代码如下 <?xml version="1.0" encod ...

  2. Android——一个简单的天气APP

    一个简单的天气APP 效果演示视频 简述 天气JSON数据 实况天气 逐24小时天气预报 未来七天天气预报 天气详情页 效果图 获取JSON数据 URL请求 实况天气URL 逐24小时天气预报URL ...

  3. Android——一个简单的音乐APP(二)

    一个简单的音乐APP 效果视频 前言 音乐下载 音乐下载效果图 实习步骤&思想 添加到下载队列 单任务下载 多任务下载 音乐下载 获取音乐下载源 创建本地路径 创建目录 开始音乐下载 下载进度 ...

  4. Android——一个简单的APP模版

    Android--一个简单的APP模版 述 效果视频 技术栈 地图.定位.导航 地图 定位 导航 偏好设置 当前导航信息 预定车位和订单结算 创建订单 计时服务传导 后台服务计时 订单结算 个人信息 ...

  5. 一个简单的手电筒APP源码分享(支持Android O(8.0)及以下版本)

    一个简单的手电筒APP(无闪光灯的设备开启屏幕照明模式) GitHub地址: https://github.com/djzhao627/SimpleTorch 打包下载 http://download ...

  6. 使用Android studio做一个简单的网站APP

    1.首先创建一个空白Android项目 2.然后打开项目,切换为Android视图,这时候会看到三个文件夹,分别是manifests.java.res.首先修改res/layout下的activity ...

  7. android studio的GearVR应用开发(二)、一个简单的VR app(Oculus官方GearVR开发教程,翻译转载)

    声明:本文是Oculus官方的GearVR开发教程,为本人翻译转载,供广大VR开发爱好者一同学习进步使用. 原文章 一个简单的VR app 概观 在搭建好GearVR框架后,让我们一起来创建第一个VR ...

  8. 简单Android手机APP地图,android最简单手机地图APP(只需5分钟)

    android最简单手机地图APP--只有三部分. 第一部分 首先建立一个MapActivity在setContentView(R.layout.activity_map);中创建一个代码如下. [h ...

  9. 编写一个简单的生日快乐APP

    编写一个简单的生日快乐APP 一.关闭之前的helloworld程序 点击file,然后close project,就完成关闭了. 二.创建一个新的happybirthday程序 三.下面开始整个AP ...

最新文章

  1. 设置显示Git的修改历史History快捷键Alt+H,方便多人开发的时候快速查看谁修改了代码
  2. 5G研发大幕开启 终端硝烟已燃
  3. LNMP,PHP开启openssl,功能扩展,K哥
  4. 【java】Charset 字符集
  5. 微型计算机普遍使用的编码是,微型计算机中普遍使用的字符编码是什么吗
  6. 使用phpunit新建项目
  7. ArrayList源码浅析
  8. docsify搭建知识库
  9. python3写网络爬虫_python3写网络爬虫
  10. linux mac docky,Ubuntu 7.10中安装酷酷的MAC风格 dock(图)
  11. JavaScript-作用域和作用域链
  12. Linux 中安装软件报缺少共享库文件的错误
  13. ruby写的BT种子解析器
  14. OFDM 调制系统框图 OFDM
  15. Mac配置Qt环境和把应用打包成dmg文件
  16. Python 支付宝红包二维码制作步骤分享
  17. python简单代码画皮卡丘-用python画一只可爱的皮卡丘
  18. 6.3 GitHub - 维护项目
  19. 智科某课小论文:当今世界计算机硬件与软件发展现状
  20. 【转自知乎】软件实施工程师-简历范文,【工作经历+项目经验+专业技能+自我评价】怎么写

热门文章

  1. QCon全球软件开发大会(北京站)将于4月25日开幕
  2. SNS背后的科学(1)从六度分隔到无尺度网络
  3. [BUAA OO Unit 2 HW8] 第二单元总结
  4. Exporter介绍与指标数据汇总(完结)
  5. Python制作Gif图片
  6. wordpress菜单显示css字体,WordPress导航菜单图标字体插件font awesome 4 menus
  7. Android 之解析XML文件
  8. uniapp Apple iOS 绑定解绑
  9. U盘空间明明够大,为什么却放不进去文件
  10. Tapd+腾讯工蜂+Jenkins持续部署