之前对系统自带的土司的源码做了简要分析,见博客:点击打开链接

这一篇给一个小案例,自定义土司,模拟腾讯卫士的小火箭发射。如果想要迅速看懂代码,建议先去看一下上篇介绍点击打开链接

首先,定义一个服务,在这个服务里面,完成土司的创建(小火箭布局创建)

烟的效果属于动画播放,而且要依托一个activity。(这个activity要定义为透明状态)

定义烟的activity的布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5.  
  6. <ImageView
  7. android:id="@+id/smoke_m"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:layout_alignParentBottom="true"
  11. android:src="@drawable/desktop_smoke_m" />
  12.  
  13. <ImageView
  14. android:layout_above="@id/smoke_m"
  15. android:id="@+id/smoke_t"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:src="@drawable/desktop_smoke_t"/>
  19.  
  20. </RelativeLayout>

在对应的Smokeactivity里面加入“烟”的动画

  1. package com.itydl.rockets;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.os.SystemClock;
  6. import android.view.animation.AlphaAnimation;
  7. import android.view.animation.Animation;
  8. import android.view.animation.AnimationSet;
  9. import android.view.animation.ScaleAnimation;
  10. import android.widget.ImageView;
  11.  
  12. public class SmokeActivity extends Activity {
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. // TODO Auto-generated method stub
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.smoke);
  18. //底部烟图片
  19. ImageView iv_m = (ImageView) findViewById(R.id.smoke_m);
  20. //烟柱子
  21. ImageView iv_t = (ImageView) findViewById(R.id.smoke_t);
  22.  
  23. //渐变动画
  24. AlphaAnimation aa = new AlphaAnimation(0.0f,1.0f);
  25. aa.setDuration(1000);
  26. //比例动画 设置锚点。x轴一半,y轴图片最低端y值最大处
  27. ScaleAnimation sa = new ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 1f);
  28. sa.setDuration(1000);
  29.  
  30. //动画集添加动画
  31.  iv_m.startAnimation(aa);//给下面这张图片实现渐变动画
  32.  
  33. AnimationSet as = new AnimationSet(true);
  34. as.addAnimation(aa);
  35. as.addAnimation(sa);
  36. //给上边图片(烟柱子)设置渐变动画和比例动画
  37. iv_t.startAnimation(as);
  38.  
  39. //1秒后关闭Activity,正好动画播完,关闭这个activity。这里也是那样,主线程动画的同时,子线程也在执行耗时操作
  40. new Thread(){
  41. public void run() {
  42. //1秒后关闭当前Activity
  43. SystemClock.sleep(1000);
  44. runOnUiThread(new Runnable() {//activity类中的方法
  45.  
  46. @Override
  47. public void run() {
  48. // TODO Auto-generated method stub
  49. finish();//关闭自己也属于更新界面操作,因此要在主线程执行。
  50. }
  51. });
  52.  
  53. };
  54. }.start();
  55.  
  56. }
  57. }

定义Service,用于自定义土司布局,加入火箭图片的动画、参数初始化、触摸事件等

  1. package com.itydl.rockets;
  2.  
  3. import android.app.Service;
  4. import android.content.Intent;
  5. import android.graphics.PixelFormat;
  6. import android.graphics.drawable.AnimationDrawable;
  7. import android.os.Handler;
  8. import android.os.IBinder;
  9. import android.os.SystemClock;
  10. import android.view.Gravity;
  11. import android.view.MotionEvent;
  12. import android.view.View;
  13. import android.view.View.OnTouchListener;
  14. import android.view.WindowManager;
  15. import android.widget.ImageView;
  16.  
  17. public class RocketService extends Service {
  18.  
  19. private WindowManager.LayoutParams params;
  20. private View view;
  21. private WindowManager wm;
  22.  
  23. @Override
  24. public IBinder onBind(Intent intent) {
  25. // TODO Auto-generated method stub
  26. return null;
  27. }
  28.  
  29. @Override
  30. public void onCreate() {
  31.  
  32. wm = (WindowManager) getSystemService(WINDOW_SERVICE);
  33.  
  34. //初始化params(土司参数)
  35. initToastParams();
  36.  
  37. showRocket();//打开小火箭
  38. super.onCreate();
  39. }
  40. /**
  41. * 初始化土司的参数
  42. */
  43. private void initToastParams() {
  44. // TODO Auto-generated method stub
  45. // XXX This should be changed to use a Dialog, with a Theme.Toast
  46. // defined that sets up the layout params appropriately.
  47.  
  48. params = new WindowManager.LayoutParams();
  49. params.height = WindowManager.LayoutParams.WRAP_CONTENT;
  50. params.width = WindowManager.LayoutParams.WRAP_CONTENT;
  51.  
  52. //对齐方式左上角
  53. params.gravity = Gravity.LEFT | Gravity.TOP;
  54. params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
  55. /* | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE */
  56. | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
  57. params.format = PixelFormat.TRANSLUCENT;
  58.  
  59. params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 土司天生不响应事件,改变类型。TYPE_SYSTEM_ALERT系统弹窗
  60. params.setTitle("Toast");
  61. }
  62.  
  63. private void closeRocket(){
  64. if (view != null) {
  65. wm.removeView(view);//移除小火箭
  66. }
  67. }
  68.  
  69. private Handler handler = new Handler(){
  70. public void handleMessage(android.os.Message msg) {
  71. wm.updateViewLayout(view, params);//更新小火箭在屏幕中的位置,刷新位置。属于更新ui。在主线程执行(更新土司的位置)
  72. };
  73. };
  74.  
  75. private void showRocket(){
  76. //小火箭的布局
  77.  
  78. view = View.inflate(getApplicationContext(), R.layout.rocket, null);
  79. ImageView iv_rocket = (ImageView) view.findViewById(R.id.iv_rocket);
  80. //获取小火箭的动画背景
  81. AnimationDrawable ad = (AnimationDrawable) iv_rocket.getBackground();
  82. //开始小火箭动画(小火箭动画,两张图片切换)
  83. ad.start();
  84.  
  85. //给小火箭加触摸事件(给自定义土司加触摸事件),按住拖动小火箭到屏幕正下方,松开发射火箭
  86. view.setOnTouchListener(new OnTouchListener() {
  87.  
  88. private float startX;
  89. private float startY;
  90.  
  91. @Override
  92. public boolean onTouch(View v, MotionEvent event) {
  93. System.out.println(event.getX() + ":" + event.getRawX());
  94. // 拖动土司
  95. switch (event.getAction()) {
  96. case MotionEvent.ACTION_DOWN:// 按下
  97. startX = event.getRawX();
  98. startY = event.getRawY();
  99. break;
  100. case MotionEvent.ACTION_MOVE:// 按下移动,拖动
  101. //新的 x y坐标
  102. float moveX = event.getRawX();//移动后的x坐标
  103. float moveY = event.getRawY();//移动后的y坐标
  104.  
  105. //dx x方向的位置变化值 dy y方向的位置变化值
  106. float dx = moveX - startX;
  107. float dy = moveY - startY;
  108. //改变土司的坐标
  109. params.x += dx;
  110. params.y += dy;
  111. //重新获取新的x y坐标
  112. startX = moveX;
  113. startY = moveY;
  114.  
  115. //更新土司的位置
  116. wm.updateViewLayout(view, params);
  117. break;
  118. case MotionEvent.ACTION_UP:// 松开,接下来要发射小火箭
  119. //判断位置 发射
  120. //x轴方向 离两边框超过100,y轴方向大于200 就可以发射火箭
  121. if (params.x > 100 && params.x + view.getWidth()< wm.getDefaultDisplay().getWidth() - 100 &&
  122. params.y > 200){
  123. //发射火箭
  124. //1,火箭往上跑
  125. //火箭在中心线上发射(自定义土司左上角为基准)
  126. params.x = (wm.getDefaultDisplay().getWidth() - view.getWidth()) / 2;
  127.  
  128. new Thread(){//发射火箭改变y轴属于耗时操作,更新火箭位置是更新UI操作
  129. public void run() {
  130. for (int j = 0; j < view.getHeight(); ) {
  131. SystemClock.sleep(50);//休眠50毫秒
  132. params.y -= j;
  133. j += 5;
  134. handler.obtainMessage().sendToTarget();//参数y的值改变一次,发消息通知更新一次ui,更新一次土司的位置
  135. }
  136.  
  137. //,发射完毕,关闭小火箭
  138. stopSelf();//关闭服务,关闭当前自己服务。这个方法用在关闭自己服务里。触发onDestroy方法,从而触发这个方法里面的关闭小火箭
  139. };
  140. }.start();
  141.  
  142. //2,烟的效果。因为更新火箭往上跑是在子线程执行的,因此在小火箭往上跑的同时,烟的效果也同时开始播放(子线程不影响主线程执行。两个线程可以同时进行)
  143. //烟的效果,是一个动画,在activity完成,这个activity需要定义为透明
  144. Intent intent = new Intent(RocketService.this,SmokeActivity.class);
  145. //在服务中打开activity,需要设置任务栈:
  146. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//任务栈
  147. startActivity(intent);//启动烟的Activity
  148. }
  149. //冒烟的Activity
  150. default:
  151. break;
  152. }
  153. return false;//默认返回值。
  154. }
  155. });
  156.  
  157. wm.addView(view, params);//把小火箭加到窗体管理器
  158. }
  159.  
  160. @Override
  161. public void onDestroy() {
  162. // TODO Auto-generated method stub
  163. closeRocket();//关闭小火箭
  164. super.onDestroy();
  165. }
  166.  
  167. }

对于主动人任务只是加入个按钮,打开这个服务就行了。

  1. package com.itydl.rockets;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.view.View;
  7.  
  8. public class MainActivity extends Activity {
  9.  
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14.  
  15. }
  16.  
  17. /**
  18. * 通过点击按钮打开小火箭
  19. * @param v
  20. */
  21. public void openRocket(View v){
  22. //RocketService service = new RocketService();
  23. Intent service = new Intent(this,RocketService.class);
  24. startService(service);//启动小火箭服务
  25. finish();//关闭当前界面。因为要显示火箭发射,不能在这个activity里面演示
  26. }
  27.  
  28. }

最后清单文件配置上两个活动和一个服务,还有一个弹出窗体的权限

  1. <activity
  2. android:name="com.itheima62.rockets.MainActivity"
  3. android:label="@string/app_name" >
  4. <intent-filter>
  5. <action android:name="android.intent.action.MAIN" />
  6.  
  7. <category android:name="android.intent.category.LAUNCHER" />
  8. </intent-filter>
  9. </activity>
  10. <!-- 配置该活动的主题,为透明、无标题、全屏 -->
  11. <activity android:name="com.itheima62.rockets.SmokeActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"></activity>
  12. <service android:name="com.itheima62.rockets.RocketService"></service>
  1. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

好了主要代码和功能都介绍完了,看一下运行效果截图:

需要完整代码请留言,或者欢迎到github上下载源代码。

Android简易实战教程--第十话《模仿腾讯手机助手小火箭发射详解》的更多相关文章

  1. Android简易实战教程--第二十话《通过广播接收者,对拨打电话外加ip号》

    没睡着觉,起来更篇文章吧哈哈!首先祝贺李宗伟击败我丹,虽然我是支持我丹的,但是他也不容易哈哈,值得尊敬的人!切入正题:这一篇来介绍个自定义广播接收者. 通常我们在外拨电话的时候,一般为使用网络电话.如 ...

  2. Android简易实战教程--第十二话《代码获取手机总运行内存的大小》

    手机RAM存储,类似于电脑的内存.这一篇,对通过代码获取手机总内存大小做详细介绍. 首先,定义一个engine类,这个类功能就是获取进程信息,包括运行的程序个数,系统总内存,系统剩余总内存.本篇先完成 ...

  3. Android简易实战教程--第十六话《SharedPreferences保存用户名和密码》

    之前在Android简易实战教程--第七话<在内存中存储用户名和密码> 那里是把用户名和密码保存到了内存中,这一篇把用户名和密码保存至SharedPreferences文件.为了引起误导, ...

  4. Android简易实战教程--第十四话《模仿金山助手创建桌面Widget小部件》

    打开谷歌api,对widget小部件做如下说明: App Widgets are miniature application views that can be embedded in otherap ...

  5. Android简易实战教程--第二十九话《创建图片副本》

    承接第二十八话加载大图片,本篇介绍如何创建一个图片的副本. 安卓中加载的原图是无法对其修改的,因为默认权限是只读的.但是通过创建副本,就可以对其做一些修改,绘制等了. 首先创建一个简单的布局.一个放原 ...

  6. Android简易实战教程--第八话《短信备份~一》

    各种手机助手里面都包含了短信备份这一项.短信的本分主要包含四项:内容body.事件date.方式type.号码address. 短信备份~一.使用一种很笨的方式来保存短信到xml文件中,而且保存在外部 ...

  7. Android简易实战教程--第二十六话《网络图片查看器在本地缓存》

    本篇接第二十五话  点击打开链接   http://blog.csdn.net/qq_32059827/article/details/52389856 上一篇已经把王略中的图片获取到了.生活中有这么 ...

  8. Android简易实战教程--第十五话《在外部存储中读写文件》

    第七话里面介绍了在内部存储读写文件 点击打开链接. 这样有一个比较打的问题,假设系统内存不够用,杀本应用无法执行,或者本应用被用户卸载重新安装后.以前保存的用户名和密码都不会得到回显.所以,有必要注意 ...

  9. Android简易实战教程--第二十八话《加载大图片》

    Android系统以ARGB表示每个像素,所以每个像素占用4个字节,很容易内存溢出.假设手机内存比较小,而要去加载一张像素很高的图片的时候,就会因为内存不足导致崩溃.这种异常是无法捕获的 内存不足并不 ...

随机推荐

  1. UVALive - 3530:Martian Mining

    dp 可以发现,对于(i,j),要么把它运上去,那么把它运到左边,枚举一下即可 #include<cstdio> #include<cstdlib> #include<a ...

  2. 使用Aes对称加密解密Web.Config数据库连接串

    现在很多公司开始为了保证数据库的安全性,通常会对Web.Config的数据库连接字符串进行加密.本文将介绍学习使用Aes加密解密数据库连接字符串.本文采用MySql数据库. AES概念简述 AES 是 ...

  3. vue中的eventBus

    在vue2中,父子组件传递数据,父组件可以直接传递数据进子组件,而子组件通过调用父组件传递进来的方法,将自己的数据传递回去. 那兄弟组件之间,或者是兄弟组件的子组件之间如何传递呢? 当然vuex是一种 ...

  4. H5canvas基础

    本篇文章开始讲解HTML5的核心功能之一:Canvas 通过Canvas可以动态生成和展示图形.图表.图像以及动画. Canvas API功能非常多,我们将讨论最常用的功能. 我们先新建一个canva ...

  5. sessionStorage 、localStorage 和 cookie

    localStorage 和 sessionStorage HTML5 提供了两种在客户端存储数据的新方法:localStorage 和 sessionStorage: 两者都是仅在客户端(即浏览器) ...

  6. 继承自 DevExpress 17.2 的自定义控件如何在工具箱显示

    最近把DevExpress版本从13.1升级到了17.2,结果发现继承自DevExpress的自定义控件居然在工具箱中消失了,弄了两天还是没有任何头绪,部分自定义Dev控件可以正常出现,但大部分自定义 ...

  7. Tarjan笔记1

    Tarjan 2822 爱在心中 ** 时间限制: 1 s ** 空间限制: 128000 KB ** 题目等级 : 钻石 Diamond 题解 题目描述 Description"每个人都拥 ...

  8. 关于Linux下软件包aptitude的相关操作

    aptitude+回车 - 进入aptitude操作界面,可以对预览查看各种软件包 aptitude show package_name - 列出与XXX相关的软件包信息,但是并不能看到该软件包所安装 ...

  9. proc文件系统探索 之 根目录下的文件[三]

    包括对proc根目录下meminfo文件的解析. > cat /proc/meminfo   读出的内核信息进行解释,下篇文章会简单对读出该信息的代码进行简单的分析. MemTotal: 507 ...

  10. Android给控件添加触摸回调

    Android给控件添加触摸回调 脑补一个场景,一个页面点击某个按钮会弹出PopupWindow,然后点击PopupWindow以外的任意位置关闭 效果图 实现方法 可以在布局的最外层容器监听触摸事件 ...