揭破android中的闹钟app 二

简介:

·  这节,我们通过wheelview来模仿一个简易的正点闹钟。

  我这里不说wheelview来龙去脉,只阐述几个简单的方法,如果,想看一看具体wheelview的内容,请看下面两篇文章:

  android 时间控件概述Android 实现 WheelView

     要实现正点闹钟,我们需要在程序中加入相应的滚轮的源代码,导入相应的源代码的结构如下所示:

 

 

  从图,我们可以得出来这样子的结论:

  ①其滚轮控件不是简简单单的完成日期时间选择,而且可以完成数字,字符串的选择,因此可以做手机的密码箱或者滚动的地址选择控件。

  ②此简单的框架(类库),运用大量的监听者,可想而知,把经典设计模式——观察者模式运用到了机制。

  好了,不东扯葫芦西扯瓢了,说一说本文的重点,时间控件的实现了。老样子,我们看代码:


  /**
     * @Description: TODO 弹出日期时间选择器
     */
    private void showDateTimePicker() {
        Calendar calendar = Calendar.getInstance();
        final int year = calendar.get(Calendar.YEAR);
        current_year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DATE);
        // 添加大小月月份并将其转换为list,方便之后的判断
        String[] months_big = { "1", "3", "5", "7", "8", "10", "12" };
        String[] months_little = { "4", "6", "9", "11" };

        final List<String> list_big = Arrays.asList(months_big);
        final List<String> list_little = Arrays.asList(months_little);

        dialog = new BaseDialog(PublicDefine.context);
        dialog.setTitle("请选择日期");
        // 找到dialog的布局文件

        View view = LayoutInflater.from(PublicDefine.context).inflate(
                R.layout.date_month_layout, null);
        //年
        final WheelView wv_year = (WheelView) view.findViewById(R.id.years);
        wv_year.setAdapter(new NumericWheelAdapter(start_year, end_year));// 设置"年"的显示数据
        wv_year.setCyclic(true);// 可循环滚动
        wv_year.setLabel("年");// 添加文字
        wv_year.setCurrentItem(year - start_year);// 初始化时显示的数据
        // 月
        final WheelView wv_month = (WheelView) view.findViewById(R.id.monthes);
        wv_month.setAdapter(new NumericWheelAdapter(1, 12));
        wv_month.setCyclic(true);
        wv_month.setLabel("月");
        wv_month.setCurrentItem(month);

        // 日
        final WheelView wv_day = (WheelView) view.findViewById(R.id.days);
        wv_day.setCyclic(true);
        // 判断大小月及是否闰年,用来确定"日"的数据
        if (list_big.contains(String.valueOf(month + 1))) {
            wv_day.setAdapter(new NumericWheelAdapter(1, 31));
        } else if (list_little.contains(String.valueOf(month + 1))) {
            wv_day.setAdapter(new NumericWheelAdapter(1, 30));
        } else {
            // 闰年
            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
                wv_day.setAdapter(new NumericWheelAdapter(1, 29));
            } else {
                wv_day.setAdapter(new NumericWheelAdapter(1, 28));
            }
        }
        wv_day.setLabel("日");
        wv_day.setCurrentItem(day - 1);


        // 添加"年"监听
        OnWheelChangedListener wheelListener_year = new OnWheelChangedListener() {
            public void onChanged(WheelView wheel, int oldValue, int newValue) {
                int year_num = newValue + start_year;
                // 判断大小月及是否闰年,用来确定"日"的数据
                if (list_big.contains(String
                        .valueOf(wv_month.getCurrentItem() + 1))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 31));
                } else if (list_little.contains(String.valueOf(wv_month
                        .getCurrentItem() + 1))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 30));
                } else {
                    if ((year_num % 4 == 0 && year_num % 100 != 0)
                            || year_num % 400 == 0) {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 29));
                    } else {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 28));
                    }
                }
            }

            @Override
            public void onEnd() {
                // TODO Auto-generated method stub
                int day=wv_day.getCurrentItem();
                day=day>wv_day.getAdapter().getItemsCount()-1?day-wv_day.getAdapter().getItemsCount():wv_day.getCurrentItem();
                wv_day.setCurrentItem(day);
            }
        };
        // 添加"月"监听
        OnWheelChangedListener wheelListener_month = new OnWheelChangedListener() {
            public void onChanged(WheelView wheel, int oldValue, int newValue) {
                int month_num = newValue + 1;
                // 判断大小月及是否闰年,用来确定"日"的数据
                if (list_big.contains(String.valueOf(month_num))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 31));
                } else if (list_little.contains(String.valueOf(month_num))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 30));
                } else {
                    if (((wv_year.getCurrentItem() + start_year) % 4 == 0 && (wv_year
                            .getCurrentItem() + start_year) % 100 != 0)
                            || (wv_year.getCurrentItem() + start_year) % 400 == 0) {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 29));
                    } else {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 28));
                    }
                }
            }

            @Override
            public void onEnd() {
                // TODO Auto-generated method stub
                int day=wv_day.getCurrentItem();
                day=day>wv_day.getAdapter().getItemsCount()-1?day-wv_day.getAdapter().getItemsCount():wv_day.getCurrentItem();
                wv_day.setCurrentItem(day);
            }
        };
        wv_month.addChangingListener(wheelListener_month);
        wv_year.addChangingListener(wheelListener_year);
// 根据屏幕密度来指定选择器字体的大小

        int textSize = 20;

        wv_day.TEXT_SIZE = (int) (textSize*RTools.getSreenDensity(PublicDefine.context));
        wv_month.TEXT_SIZE = (int) (textSize*RTools.getSreenDensity(PublicDefine.context));
        wv_year.TEXT_SIZE=(int) (textSize*RTools.getSreenDensity(PublicDefine.context));    
        Button btn_sure = (Button) view.findViewById(R.id.btn_datetime_sure);
        Button btn_cancel = (Button) view
                .findViewById(R.id.btn_datetime_cancel);


        // 确定
        btn_sure.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                // 如果是个数,则显示为"02"的样式
                String parten = "00";
                DecimalFormat decimal = new DecimalFormat(parten);
                // 设置日期的显示
                select_month = wv_month.getCurrentItem() + 1;
                select_day = wv_day.getCurrentItem() + 1;
                select_year=wv_year.getCurrentItem()+start_year;
                String aa = (wv_year.getCurrentItem()+start_year)+"-"+(decimal.format((wv_month.getCurrentItem() + 1))
                        + "-" + decimal.format((wv_day.getCurrentItem() + 1)));
                date_select.setText(aa);

                dialog.dismiss();
            }
        });
        // 取消
        btn_cancel.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                dialog.dismiss();
            }
        });
        // 设置dialog的布局,并显示
        dialog.setContentView(view);
        dialog.show();
    }

 由这长段的源代码,我们可以得出这样的总结了:

  ①获取当前的日期,显示到相应的时间选择器中。

  ②利用大小月天数,对相应的大小月天数进行保存。

  ③添加相应的填充器,对月份滚轮,年分滚轮的数据进行了一系列的填充。

  ④并且根据月份,是否闰年等相关的条件, 对其天数的滚轮进行了填充。

     ⑤也是我重点要提的一个方法,对其移动后的时间滚轮所指向的天数进行调整,这是解决一个什么问题了,就是倘若滚动到3月31日时候,月份再次拨回四的时候,此时应该指向4月1日啊。这个就是onend方法所做的事情了。

综上所述,一个闹钟app就此ok了,其效果如下图:


目录
相关文章
|
3月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
236 0
安卓项目:app注册/登录界面设计
|
3天前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
|
4月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
153 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
4月前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
319 2
|
4月前
|
XML Android开发 数据格式
🌐Android国际化与本地化全攻略!让你的App走遍全球无障碍!🌍
在全球化背景下,实现Android应用的国际化与本地化至关重要。本文以一款旅游指南App为例,详细介绍如何通过资源文件拆分与命名、适配布局与方向、处理日期时间及货币格式、考虑文化习俗等步骤,完成多语言支持和本地化调整。通过邀请用户测试并收集反馈,确保应用能无缝融入不同市场,提升用户体验与满意度。
138 3
|
4月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
123 10
|
3月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
406 0
|
4月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
5月前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
79 1
|
5月前
|
Android开发 iOS开发 C#
Xamarin:用C#打造跨平台移动应用的终极利器——从零开始构建你的第一个iOS与Android通用App,体验前所未有的高效与便捷开发之旅
【8月更文挑战第31天】Xamarin 是一个强大的框架,允许开发者使用单一的 C# 代码库构建高性能的原生移动应用,支持 iOS、Android 和 Windows 平台。作为微软的一部分,Xamarin 充分利用了 .NET 框架的强大功能,提供了丰富的 API 和工具集,简化了跨平台移动应用开发。本文通过一个简单的示例应用介绍了如何使用 Xamarin.Forms 快速创建跨平台应用,包括设置开发环境、定义用户界面和实现按钮点击事件处理逻辑。这个示例展示了 Xamarin.Forms 的基本功能,帮助开发者提高开发效率并实现一致的用户体验。
195 0