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

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

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

烟的效果属于动画播放,而且要依托一个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简易实战教程--第十话《模仿腾讯手机助手小火箭发射详解》的更多相关文章

  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. Codeforces Round #408 (Div. 2)

    C. Bank Hacking 题目大意:给出一棵n个节点的树,每个节点有一个权值,删掉一个点的代价为当前这个点的权值,并且会使其相邻点和距离为2且中间隔着未被删除的点的点权值加1,现在选一个点开始删 ...

  2. [BZOJ]1069: [SCOI2007]最大土地面积

    题目大意:给出二维平面上n个点,求最大的由这些点组成的四边形面积.(n<=2000) 思路:求出凸包后旋转卡壳枚举对踵点对作为四边形的对角线,枚举或二分另外两个点,复杂度O(n^2)或O(nlo ...

  3. 【bzoj4567 scoi2016】 背单词

    题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...

  4. hdu 5463(水水)

    Sample Input 2 3 2 33 3 33 2 33 10 5 467 6 378 7 309 8 499 5 320 3 480 2 444 8 391 5 333 100 499   S ...

  5. poj 1367 robot(搜索)

    题意:给你一个图,求起点 到 终点的最少时间 每次有两种选择①:往前走1~3步                ②原地选择90°   费时皆是1s 图中1为障碍物,而且不能出边界.还要考虑机器人的直径 ...

  6. 如何用Netty实现一个轻量级的HTTP代理服务器

    为什么会想通过Netty构建一个HTTP代理服务器?这也是笔者发表这篇文章的目的所在. 其主要还是源于解决在日常开发测试过程中,一直困扰测试同学很久的一个问题,现在我就来具体阐述一下这个问题. 在日常 ...

  7. dev gridcontrol 无法编辑 解决方案

    1.确认表格打开编辑 gridView1.OptionsBehavior.Editable = True 2.确认列打开编辑 gridView1.Columns("Name").O ...

  8. Safari 3D transform变换z-index层级渲染异常

    (猛戳来源:http://www.zhangxinxu.com/wordpress/?p=5569)

  9. SVN提交时显示:Path is not a working copy directory

    说明你地址没有checkout啊 先checkout,才能add和commi. 要是在一个已有的项目出现这个错误,就是包含这个地址的文件夹没添加进去,去上一层再试一次. 总之,养成在项目根目录提交的习 ...

  10. 转:Kafka 客户端TimeoutException问题之坑

    原文出自:http://www.jianshu.com/p/2db7abddb9e6 各种TimeoutException问题 会抛出org.apache.kafka.common.errors.Ti ...