Android简易实战教程--第十话《模仿腾讯手机助手小火箭发射详解》
之前对系统自带的土司的源码做了简要分析,见博客:点击打开链接
这一篇给一个小案例,自定义土司,模拟腾讯卫士的小火箭发射。如果想要迅速看懂代码,建议先去看一下上篇介绍点击打开链接
首先,定义一个服务,在这个服务里面,完成土司的创建(小火箭布局创建)
烟的效果属于动画播放,而且要依托一个activity。(这个activity要定义为透明状态)
定义烟的activity的布局文件
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <ImageView
- android:id="@+id/smoke_m"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:src="@drawable/desktop_smoke_m" />
- <ImageView
- android:layout_above="@id/smoke_m"
- android:id="@+id/smoke_t"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/desktop_smoke_t"/>
- </RelativeLayout>
在对应的Smokeactivity里面加入“烟”的动画
- package com.itydl.rockets;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.SystemClock;
- import android.view.animation.AlphaAnimation;
- import android.view.animation.Animation;
- import android.view.animation.AnimationSet;
- import android.view.animation.ScaleAnimation;
- import android.widget.ImageView;
- public class SmokeActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.smoke);
- //底部烟图片
- ImageView iv_m = (ImageView) findViewById(R.id.smoke_m);
- //烟柱子
- ImageView iv_t = (ImageView) findViewById(R.id.smoke_t);
- //渐变动画
- AlphaAnimation aa = new AlphaAnimation(0.0f,1.0f);
- aa.setDuration(1000);
- //比例动画 设置锚点。x轴一半,y轴图片最低端y值最大处
- ScaleAnimation sa = new ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 1f);
- sa.setDuration(1000);
- //动画集添加动画
- iv_m.startAnimation(aa);//给下面这张图片实现渐变动画
- AnimationSet as = new AnimationSet(true);
- as.addAnimation(aa);
- as.addAnimation(sa);
- //给上边图片(烟柱子)设置渐变动画和比例动画
- iv_t.startAnimation(as);
- //1秒后关闭Activity,正好动画播完,关闭这个activity。这里也是那样,主线程动画的同时,子线程也在执行耗时操作
- new Thread(){
- public void run() {
- //1秒后关闭当前Activity
- SystemClock.sleep(1000);
- runOnUiThread(new Runnable() {//activity类中的方法
- @Override
- public void run() {
- // TODO Auto-generated method stub
- finish();//关闭自己也属于更新界面操作,因此要在主线程执行。
- }
- });
- };
- }.start();
- }
- }
定义Service,用于自定义土司布局,加入火箭图片的动画、参数初始化、触摸事件等
- package com.itydl.rockets;
- import android.app.Service;
- import android.content.Intent;
- import android.graphics.PixelFormat;
- import android.graphics.drawable.AnimationDrawable;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.SystemClock;
- import android.view.Gravity;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.View.OnTouchListener;
- import android.view.WindowManager;
- import android.widget.ImageView;
- public class RocketService extends Service {
- private WindowManager.LayoutParams params;
- private View view;
- private WindowManager wm;
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public void onCreate() {
- wm = (WindowManager) getSystemService(WINDOW_SERVICE);
- //初始化params(土司参数)
- initToastParams();
- showRocket();//打开小火箭
- super.onCreate();
- }
- /**
- * 初始化土司的参数
- */
- private void initToastParams() {
- // TODO Auto-generated method stub
- // XXX This should be changed to use a Dialog, with a Theme.Toast
- // defined that sets up the layout params appropriately.
- params = new WindowManager.LayoutParams();
- params.height = WindowManager.LayoutParams.WRAP_CONTENT;
- params.width = WindowManager.LayoutParams.WRAP_CONTENT;
- //对齐方式左上角
- params.gravity = Gravity.LEFT | Gravity.TOP;
- params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- /* | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE */
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
- params.format = PixelFormat.TRANSLUCENT;
- params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 土司天生不响应事件,改变类型。TYPE_SYSTEM_ALERT系统弹窗
- params.setTitle("Toast");
- }
- private void closeRocket(){
- if (view != null) {
- wm.removeView(view);//移除小火箭
- }
- }
- private Handler handler = new Handler(){
- public void handleMessage(android.os.Message msg) {
- wm.updateViewLayout(view, params);//更新小火箭在屏幕中的位置,刷新位置。属于更新ui。在主线程执行(更新土司的位置)
- };
- };
- private void showRocket(){
- //小火箭的布局
- view = View.inflate(getApplicationContext(), R.layout.rocket, null);
- ImageView iv_rocket = (ImageView) view.findViewById(R.id.iv_rocket);
- //获取小火箭的动画背景
- AnimationDrawable ad = (AnimationDrawable) iv_rocket.getBackground();
- //开始小火箭动画(小火箭动画,两张图片切换)
- ad.start();
- //给小火箭加触摸事件(给自定义土司加触摸事件),按住拖动小火箭到屏幕正下方,松开发射火箭
- view.setOnTouchListener(new OnTouchListener() {
- private float startX;
- private float startY;
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- System.out.println(event.getX() + ":" + event.getRawX());
- // 拖动土司
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:// 按下
- startX = event.getRawX();
- startY = event.getRawY();
- break;
- case MotionEvent.ACTION_MOVE:// 按下移动,拖动
- //新的 x y坐标
- float moveX = event.getRawX();//移动后的x坐标
- float moveY = event.getRawY();//移动后的y坐标
- //dx x方向的位置变化值 dy y方向的位置变化值
- float dx = moveX - startX;
- float dy = moveY - startY;
- //改变土司的坐标
- params.x += dx;
- params.y += dy;
- //重新获取新的x y坐标
- startX = moveX;
- startY = moveY;
- //更新土司的位置
- wm.updateViewLayout(view, params);
- break;
- case MotionEvent.ACTION_UP:// 松开,接下来要发射小火箭
- //判断位置 发射
- //x轴方向 离两边框超过100,y轴方向大于200 就可以发射火箭
- if (params.x > 100 && params.x + view.getWidth()< wm.getDefaultDisplay().getWidth() - 100 &&
- params.y > 200){
- //发射火箭
- //1,火箭往上跑
- //火箭在中心线上发射(自定义土司左上角为基准)
- params.x = (wm.getDefaultDisplay().getWidth() - view.getWidth()) / 2;
- new Thread(){//发射火箭改变y轴属于耗时操作,更新火箭位置是更新UI操作
- public void run() {
- for (int j = 0; j < view.getHeight(); ) {
- SystemClock.sleep(50);//休眠50毫秒
- params.y -= j;
- j += 5;
- handler.obtainMessage().sendToTarget();//参数y的值改变一次,发消息通知更新一次ui,更新一次土司的位置
- }
- //,发射完毕,关闭小火箭
- stopSelf();//关闭服务,关闭当前自己服务。这个方法用在关闭自己服务里。触发onDestroy方法,从而触发这个方法里面的关闭小火箭
- };
- }.start();
- //2,烟的效果。因为更新火箭往上跑是在子线程执行的,因此在小火箭往上跑的同时,烟的效果也同时开始播放(子线程不影响主线程执行。两个线程可以同时进行)
- //烟的效果,是一个动画,在activity完成,这个activity需要定义为透明
- Intent intent = new Intent(RocketService.this,SmokeActivity.class);
- //在服务中打开activity,需要设置任务栈:
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//任务栈
- startActivity(intent);//启动烟的Activity
- }
- //冒烟的Activity
- default:
- break;
- }
- return false;//默认返回值。
- }
- });
- wm.addView(view, params);//把小火箭加到窗体管理器
- }
- @Override
- public void onDestroy() {
- // TODO Auto-generated method stub
- closeRocket();//关闭小火箭
- super.onDestroy();
- }
- }
对于主动人任务只是加入个按钮,打开这个服务就行了。
- package com.itydl.rockets;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
- /**
- * 通过点击按钮打开小火箭
- * @param v
- */
- public void openRocket(View v){
- //RocketService service = new RocketService();
- Intent service = new Intent(this,RocketService.class);
- startService(service);//启动小火箭服务
- finish();//关闭当前界面。因为要显示火箭发射,不能在这个activity里面演示
- }
- }
最后清单文件配置上两个活动和一个服务,还有一个弹出窗体的权限
- <activity
- android:name="com.itheima62.rockets.MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <!-- 配置该活动的主题,为透明、无标题、全屏 -->
- <activity android:name="com.itheima62.rockets.SmokeActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"></activity>
- <service android:name="com.itheima62.rockets.RocketService"></service>
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
好了主要代码和功能都介绍完了,看一下运行效果截图:
需要完整代码请留言,或者欢迎到github上下载源代码。
Android简易实战教程--第十话《模仿腾讯手机助手小火箭发射详解》的更多相关文章
- Android简易实战教程--第二十话《通过广播接收者,对拨打电话外加ip号》
没睡着觉,起来更篇文章吧哈哈!首先祝贺李宗伟击败我丹,虽然我是支持我丹的,但是他也不容易哈哈,值得尊敬的人!切入正题:这一篇来介绍个自定义广播接收者. 通常我们在外拨电话的时候,一般为使用网络电话.如 ...
- Android简易实战教程--第十二话《代码获取手机总运行内存的大小》
手机RAM存储,类似于电脑的内存.这一篇,对通过代码获取手机总内存大小做详细介绍. 首先,定义一个engine类,这个类功能就是获取进程信息,包括运行的程序个数,系统总内存,系统剩余总内存.本篇先完成 ...
- Android简易实战教程--第十六话《SharedPreferences保存用户名和密码》
之前在Android简易实战教程--第七话<在内存中存储用户名和密码> 那里是把用户名和密码保存到了内存中,这一篇把用户名和密码保存至SharedPreferences文件.为了引起误导, ...
- Android简易实战教程--第十四话《模仿金山助手创建桌面Widget小部件》
打开谷歌api,对widget小部件做如下说明: App Widgets are miniature application views that can be embedded in otherap ...
- Android简易实战教程--第二十九话《创建图片副本》
承接第二十八话加载大图片,本篇介绍如何创建一个图片的副本. 安卓中加载的原图是无法对其修改的,因为默认权限是只读的.但是通过创建副本,就可以对其做一些修改,绘制等了. 首先创建一个简单的布局.一个放原 ...
- Android简易实战教程--第八话《短信备份~一》
各种手机助手里面都包含了短信备份这一项.短信的本分主要包含四项:内容body.事件date.方式type.号码address. 短信备份~一.使用一种很笨的方式来保存短信到xml文件中,而且保存在外部 ...
- Android简易实战教程--第二十六话《网络图片查看器在本地缓存》
本篇接第二十五话 点击打开链接 http://blog.csdn.net/qq_32059827/article/details/52389856 上一篇已经把王略中的图片获取到了.生活中有这么 ...
- Android简易实战教程--第十五话《在外部存储中读写文件》
第七话里面介绍了在内部存储读写文件 点击打开链接. 这样有一个比较打的问题,假设系统内存不够用,杀本应用无法执行,或者本应用被用户卸载重新安装后.以前保存的用户名和密码都不会得到回显.所以,有必要注意 ...
- Android简易实战教程--第二十八话《加载大图片》
Android系统以ARGB表示每个像素,所以每个像素占用4个字节,很容易内存溢出.假设手机内存比较小,而要去加载一张像素很高的图片的时候,就会因为内存不足导致崩溃.这种异常是无法捕获的 内存不足并不 ...
随机推荐
- 【LSGDOJ 1408】邮局
题目描述 一些村庄被建在一条笔直的高边公路边上.我们用一条坐标轴来描述这条高边公路,每一个村庄的坐标都是整数.没有两个村庄坐标相同.两个村庄问的距离,定义为它们坐标值差的绝对值. 我们需要在一些村庄建 ...
- Django中数据查询(万能下换线,聚合,F,Q)
数据查询中万能的下划线基本用法: __contains: 包含 __icontains: 包含(忽略大小写) __startswith: 以什么开头 __istartswith: 以什么开头(忽略大小 ...
- Unix系统的文件目录项的内容是什么,这样处理的好处是什么?
(Unix系统采用树型目录结构,而且目录中带有交叉勾链.每个目录表称为一个目录文件.一个目录文件是由目录项组成的.) 每个目录项包含16个字节,一个辅存磁盘块(512B)包含32个目录项.在目录项中, ...
- RabbitMQ-Spring AMQP
上篇文章RabbitMQ基础入门学习了rabbitMQ一些基础的api,当然spring也在原生代码的基础上做了更多的封装,这篇文章就基于spring-rabbit,学习一下spring的实现. p. ...
- Python 中的 if __name__ == '__main__' 该如何理解
__name__ 表示当前模块名, __main__ 表示正在运行的模块名. if __name__ == '__main__' 这句话的意思就是,当模块被直接运行时,以下代码块将被运行,当模块是被导 ...
- Delphi 打印 Tprinter
打印 打印对于许多 Windows 程序员来说是十分棘手的问题. Delphi 简化了打印时用户所必须了解的大部分内容.用户可以很轻松地写出简单的打印程序来输出文本和位图化了的图像. ...
- C语言作业程序设计第一次作业
1.求圆面积和面积 (1)题目: 输入圆的半径,计算圆的周长和面积 (2)流程图: (3)测试数据及运行结果 测试数据:r=4 运行结果: (4)实验分析 没有遇到问题 2.判断闰年问题 (1)题目: ...
- getBoundingClientRect方法获取元素在页面中的相对位置
获取元素位置可以用 offset 或 getBoundingClientRect,使用 offset 因为兼容性不好,比较麻烦,offset获取位置会形成"回溯".而 getBou ...
- swiper实现臭美app滑动效果
一.臭美app效果: 我的需求是这样,上面正常滑动,点击下面的小卡牌,上面的滑动区也随之切换到当前的点击态. 二.实现: css: 主要设置可见区域的几张卡牌的位置,注意的几个位置是,中间的激活态和左 ...
- Create database 创建数据库
首先在ORACLE用户下进入.bash_profile文件 [oracle@linux02 ~]$ vi .bash_profile export ORACLE_SID=hldbexport ORAC ...