android——一个简单的闹钟app(代码片段)

FranzLiszt1847 FranzLiszt1847     2023-02-05     300

关键词:

效果视频

闹钟子项

子项布局效果图

闹钟适配器类

本示例采用的是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() 
            @Override
            public void onClick(View v) 
                DeleteItem(position);
            
         );
        holder.ClockSwitch.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() 
            @Override
            public 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() 
            @Override
            public 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,即显示一个时钟,通过滑动指针选择时间

 <TimePicker
           android: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申明即可

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

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

timePicker.setOnTimeChangedListener( new TimePicker.OnTimeChangedListener() 
            @Override
            public 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"/>
<!-- 变化率 -->
<gradient
    android: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"/>
<!-- 变化率 -->
<gradient
    android: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"/>
        <!-- 变化率  定义从左到右的颜色不变 -->
        <gradient
            android: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
    @Override
    public IBinder onBind(Intent intent) 
        return null;
    

    @Override
    public 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 );
    

    @Override
    public 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--闹钟小程序(broadcast实现)(代码片段)

1.定义闹钟的提示Activity程序类-AlarmManagerpackageorg.lxh.demo;importjava.sql.Date;importjava.text.SimpleDateFormat;importandroid.app.Activity;importandroid.app.AlertDialog;importandroid.content.DialogInterface 查看详情

android项目实战(二十二):启动另一个appor重启本app(代码片段)

原文:Android项目实战(二十二):启动另一个APPor重启本APP一、启动另一个APP目前公司项目需求,一个主APP,需要打开某些小APP,这些小APP是整合了Unity的,但是还是android程序(所有小APP的包名是已知的)。以前没做过,查询了一... 查看详情

android闹钟遇到的那些坑(代码片段)

...间有多少坑了。第一次做闹钟程序是在2012年,那时候android最新版本是2.2,2.3发布在即,做了一个整点提醒的小工具,记得很清楚,主要的问题是锁屏之后闹钟不能准时被唤醒,总会晚那么几秒钟,后... 查看详情

基于cordova的b站用户直播闹钟app(安卓版)(代码片段)

前言本项目基于Cordova开发,打包的apk支持Android9+,主要功能为监听b站用户直播情况,开播进行闹钟提示ps:目前版本还是有蛮多问题的,如有遇到可以及时反馈,我会想办法进行修复。源码下载码云GitH... 查看详情

基于cordova的b站用户直播闹钟app(安卓版)(代码片段)

前言本项目基于Cordova开发,打包的apk支持Android9+,主要功能为监听b站用户直播情况,开播进行闹钟提示ps:目前版本还是有蛮多问题的,如有遇到可以及时反馈,我会想办法进行修复。源码下载码云GitH... 查看详情

android中使用alarmmanager设置闹钟详解(代码片段)

...="1.0"encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_pare... 查看详情

android使用webview打包网页成app(代码片段)

...成app,可以提高开发速度,还能基本实现跨平台。下面以Android为例,在ubuntu-14.04.4-desktop-amd64环境实现一个简单的WebView封装网站成app的过程。 环境准备开发环境需要JavaSDK(官网下载),AndroidSDK(官网下载)。JavaSDK安 查看详情

android逆向工具简单介绍(代码片段)

目录一、Android逆向概述1、什么是Android逆向2、逆向过程3、逆向用途1)APP自动化执行程序脚本2)修改APP的功能3)APP安全二、常用逆向工具介绍1、APP抓包工具1)Fiddler2)Wireshark2、jadx反编译工具3、APKDB4、Frida之... 查看详情

使用alarmmanager设置闹钟(代码片段)

...in.xml:1<?xmlversion="1.0"encoding="utf-8"?>2<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"3xmlns:app="http://schemas.android.com/apk/res-auto"4xmlns:tools="http://schemas.android.com/tools"5android:layout_width="match_parent"6android:layout_height="match_parent"7... 查看详情

android热修复手动实现(代码片段)

前言热修复,简单的说就是在不重新下载安装app的情况下,自动修复现有app的问题,今天来做一个简单的实现。效果图点击TEST我们执行下面的方法publicvoidtest(Viewview)TestCaculatetestCaculate=newTestCaculate();testCaculate.caculate... 查看详情

android自定义闹钟(代码片段)

...荐方式3种:一、AlarmManagersetRepeating() 重复闹钟。1、Android4.4(API级别19)开始,所有重复闹钟都是不精确的,延时2分钟左右。2、闹钟触发的待定Intent。当您设置使用同一待定Intent的第二个闹钟时,它会替... 查看详情

Timer App 类似 4.2 时钟闹钟

...闹钟。输入名称和分钟:秒,单击+(例如),它会创建一个类似卡片的元素(甚至不是下拉或其他东西),我可以单击它来启动计时器或长按删除。有没有简单的方法来添加它,还是我必须从头开始创建它?此外,新的时间 查看详情

android一个app打开另一个app的指定页面(代码片段)

一个app打开另一个app的指定页面方法有以下几种     1、通过包名、类名   2、通过intent的action   3、通过Url  方案1、ComponentNamecomponentName=newComponentName("com.example.bi" 查看详情

android之实现多桌面图标app入口进入不同的页面,像2个独立运行的app一样,互不干扰。(代码片段)

1、需求Android实现2个图标app入口进入不同的页面,一个图标点击进去主app页面,一个图标点击直接进入app页面的里面一个子页面,两个图标功能点击效果独立,不能乱跳,副桌面图标然后返回也是直接返回,不能先返回到本地,... 查看详情

stm32的闹钟(代码片段)

...间(不指定就是明天的同一时间醒来执行任务)。看似很简单,我想肯定就是半天的功夫了。星期一开始干,在网上查看教程,结果全部是标准库的,方法繁琐,我的工程文件是HAL库的,是 查看详情

牛牛的闹钟(代码片段)

...,请问他最晚可以什么时间起床输入描述:每个输入包含一个测试用例。 每个测试用例的第一行包含一个正整数,表示闹钟的数量N。 接下来的N行每行包含两个整数,表示这个闹钟响起的时间为分。 接下来的一行包... 查看详情

android编写一个视频监控app(代码片段)

Android编写一个视频监控App很久没写app了,小项目需要写一个rtmp拉流的视频监控app,简单记录一下。参考:Android实现rtmp推拉流摄像头(三)_空空7的博客-CSDN博客_androidrtmp拉流相关库引用外部库首先添加这个到... 查看详情

android热修复原来这么简单(代码片段)

...码。这样就省事多了,用户体验也好。二、热修复的原理1.Android的 查看详情