Android之极致拟物化空气质量检测仪

来源:互联网 发布:期货从业软件 编辑:程序博客网 时间:2024/04/28 05:58

声明:转载此文请注明出处!源创意出自:https://play.google.com/store/apps/details?id=us.bestapp.pm25


本文源码:http://download.csdn.net/detail/weidi1989/5789763 

(源码是基于eclipse工程打包,utf-8编码,如果遇到导入出错的童鞋,请自行找度娘或谷哥帮忙,谢谢合作!)


今天,跟大家分享一个重量级的小工具,可以说是极致拟物化。虽然功能很简单,但是效果很逼真,很酷!大家尽情的踩吧~

下面我们就来看看效果图:

1.显示北京市当前的AQI,可以通过NEXT键切换AQI与PM2.5值。

2.点击PRINT,就会有打印机一样的动画展现一份质量检测报告,同时有逼真的打印机声音,我们还可以点击分享按钮,分享给我们的朋友。

3.纸张可以通过滑动来撕掉此纸张,同时会有逼真的撕纸声音。(注意:Android3.0以下机器不支持撕纸动画)

4.长按PRINT,即可展示反馈界面,请填写您想说的话,然后通过软键盘的ENTER键确认,将会以邮件的形式反馈给我。

   

   


说明
提供实时查询全国 76 个城市(共 509 个监测点)的空气质量监测数据,为健康生活提供指引。支持分享到社交网络。
【操作提示】
* 按 NEXT :切换显示【AQI 指数】与【PM2.5 浓度值】
* 按 PRINT :打印具体空气质量详情
* 长按 NEXT :进入选择城市模式
* ……
* 更多操作方式,慢慢探索 :大笑
忘记从什么时候开始,用颜色表示空气;
不知道什么时候可以,用甜度描述空气。
PM2.5 空气质量监测仪,就是这么简单,就是这么精致!


好了,下面重点跟大家讲讲源代码,其实功能很简单,就是拟物化的动画效果花了点小心思,这里,我引入了nineoldandroids-2.4.0.jar这个第三方库,因为在Android3.0以下的API中,有些动画是不支持的。

先看看源码结构图:

   

本例所有的动画都封装在一个类中,我们来看看:

[java] view plain copy
  1. /** 
  2.  * 所以动画的封装 用到第三方包nineoldandroids中的 Animator、AnimatorSet、ObjectAnimator 
  3.  *  
  4.  * @author way 
  5.  *  
  6.  */  
  7. public final class PM25Anim {  
  8.     /** 
  9.      * 水平平移动画 
  10.      *  
  11.      * @param view 
  12.      * @param x 
  13.      * @return 
  14.      */  
  15.     public static Animator add(final View view, float x) {  
  16.         ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,  
  17.                 "translationX"new float[] { x, 0.0F });  
  18.         objectAnimator.setDuration(1000L);  
  19.         objectAnimator.addListener(new Animator.AnimatorListener() {  
  20.             public void onAnimationCancel(Animator paramAnonymousAnimator) {  
  21.             }  
  22.   
  23.             public void onAnimationEnd(Animator animator) {  
  24.             }  
  25.   
  26.             public void onAnimationRepeat(Animator animator) {  
  27.             }  
  28.   
  29.             public void onAnimationStart(Animator animator) {  
  30.                 view.setVisibility(View.VISIBLE);  
  31.             }  
  32.         });  
  33.         return objectAnimator;  
  34.     }  
  35.   
  36.     /** 
  37.      * 从原点向下移动动画 
  38.      *  
  39.      * @param view 
  40.      *            需要加入动画的view 
  41.      * @param y 
  42.      *            需要移动到的轴坐标 
  43.      * @return 动画对象Animator 
  44.      */  
  45.     public static Animator down(View view, float y) {  
  46.         ObjectAnimator localObjectAnimator = ObjectAnimator.ofFloat(view,  
  47.                 "translationY"new float[] { 0.0F, y });  
  48.         localObjectAnimator.setDuration(2000L);  
  49.         return localObjectAnimator;  
  50.     }  
  51.   
  52.     /** 
  53.      * 从y轴原点向上移动到指定y坐标 
  54.      *  
  55.      * @param view 
  56.      *            需要加入动画的view 
  57.      * @param y 
  58.      *            终止y轴坐标 
  59.      * @return 动画对象Animator 
  60.      */  
  61.     public static Animator up(View view, float y) {  
  62.         ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,  
  63.                 "translationY"new float[] { 0.0F, y });  
  64.         objectAnimator.setDuration(2000L);  
  65.         return objectAnimator;  
  66.     }  
  67.   
  68.     /** 
  69.      * 向上移动的动画 
  70.      *  
  71.      * @param view 
  72.      *            需要加入动画的view 
  73.      * @param fromY 
  74.      *            起始y轴坐标 
  75.      * @param toY 
  76.      *            终止y轴坐标 
  77.      * @return 动画对象Animator 
  78.      */  
  79.     public static Animator up(View view, float fromY, float toY) {  
  80.         ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,  
  81.                 "translationY"new float[] { fromY, toY });  
  82.         objectAnimator.setDuration(2000L);  
  83.         return objectAnimator;  
  84.     }  
  85.   
  86.     /** 
  87.      * 向上移动并渐变消失 
  88.      *  
  89.      * @param view 
  90.      *            需要加入动画的view 
  91.      * @param y 
  92.      *            向上移动的距离 
  93.      * @return 动画对象Animator 
  94.      */  
  95.     public static Animator upAndVanish(View view, float y) {  
  96.         AnimatorSet animatorSet = new AnimatorSet();  
  97.         Animator[] arrayOfAnimator = new Animator[2];  
  98.         float[] floats = new float[2];  
  99.         floats[0] = y;  
  100.         floats[1] = (3.0F * y);  
  101.         arrayOfAnimator[0] = ObjectAnimator.ofFloat(view, "translationY",  
  102.                 floats);  
  103.         arrayOfAnimator[1] = ObjectAnimator.ofFloat(view, "alpha"new float[] {  
  104.                 1.0F, 0.0F });  
  105.         animatorSet.playTogether(arrayOfAnimator);  
  106.         animatorSet.setDuration(2000L);  
  107.         return animatorSet;  
  108.     }  
  109. }  


然后在我们的PM25Activity中实例化这些动画,包括纸张打印、模拟检测拟的向下移动、以及纸张撕掉的动画(我这里只贴出动画部分代码):

[java] view plain copy
  1. mBodyTranslate = PM25Anim.down(this.mBodyLayout, getResources()  
  2.             .getDimension(R.dimen.paper_anim_down));//打印纸张时总体向下移动动画  
  3.     mPaperUpTitle = PM25Anim.up(this.mPaperLayout, getResources()  
  4.             .getDimension(R.dimen.paper_anim_up_one));//最初打印一个标题时纸张移动向上动画  
  5.     mPaperUpAll = PM25Anim.up(this.mPaperLayout, getResources()  
  6.             .getDimension(R.dimen.paper_anim_up_one), getResources()  
  7.             .getDimension(R.dimen.paper_anim_up_two));//整张纸打印向上的动画  
  8.     mFeedbackSended = PM25Anim.upAndVanish(this.mPaperLayout,  
  9.             getResources().getDimension(R.dimen.paper_anim_up_two));//反馈消息发送时,纸张渐变动画  
  10.     mBodyReset = PM25Anim.up(this.mBodyLayout,  
  11.             getResources().getDimension(R.dimen.paper_anim_down), 0.0F);//撕掉纸张时,仪器恢复原状的向上动画  


OK,动画效果就总结到这里了,下面我们来分析一下自动定位的原理:目前看到大部分国内软件定位都是直接使用百度轻量级的包定位,包括我之前的那个简洁天气,也是如此,在这里,我使用的Google定位,换一种方式,换一个心情,多多熟练一下不同的方式。主要方法就是通过手机可用的PROVIDER,包括PASSIVE_PROVIDER、NETWORK_PROVIDER、GPS_PROVIDER三种方式,选择一个最优的方式定位,获取当前位置坐标点,然后通过HTTP请求,获取当前的城市名,例如:http://maps.googleapis.com/maps/api/geocode/json?latlng=22.5329294,114.019329&sensor=true,我们可以替换其中的latlng参数为手机获取的地理坐标,就可以获得城市名,虽然总体比百度jar包麻烦一点,但也算是最原始的一种方式了。通过网页访问这个网站,我们发现返回一大堆数据,这就需要我们解析了,这里我也贴出解析出城市的代码:

[java] view plain copy
  1. JSONArray jsonArray = new JSONObject(result)  
  2.                                     .getJSONArray("results").getJSONObject(0)  
  3.                                     .getJSONArray("address_components");  
  4.                             for (int i = 0; i < jsonArray.length(); ++i) {  
  5.                                 JSONObject jsonObject = jsonArray  
  6.                                         .getJSONObject(i);  
  7.                                 String types = jsonObject.getJSONArray("types")  
  8.                                         .toString();  
  9.                                 if ((types.contains("locality"))  
  10.                                         && (types.contains("political"))  
  11.                                         && (!types.contains("sublocality"))) {  
  12.                                     Log.d(LogTag, jsonObject.toString());  
  13.                                     city = jsonObject.getString("short_name");  
  14.                                     Log.d(LogTag, city);  
  15.   
  16.                                 }  
  17.                             }  

另外,其实我们还可以HTTP请求百度服务器,将地理坐标转换成城市,我这里就只提一下,解析原理也是类似的,都是json格式的返回数据:http://api.map.baidu.com/geocoder/v2/?ak=1919b4b56ae680106f8d1dfa5f7244d9&location=22.5329294,114.019329&output=json。


OK,本文大概的内容就是这样了,有需要的童鞋,可以下载源码参考参考,最后提醒一下,由于时间、人手问题,bug是在所难免的,目前已知bug:

1.频繁点击button,包括长按短按,会造成boolean标志位混乱。

2.撕纸张时,如果纸张角度较大且一直触屏,会造成纸张循环旋转。

3.偶尔会有动画卡顿的情况。

4.可能会有屏幕分辨率不适配的情况。

5.......

0 0
原创粉丝点击