先上演示效果
1、MainActivity
主布局就两个Button按钮 :一开启、二关闭 就不贴主布局xml了
因为小火箭是游离在activity之外的,所以不能依赖activity的生命周期
需要注意的一点是不要忘记在清单文件里配置 service
贴一下代码:
public class MainActivity extends Activity {
private Button open,close;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化
*/
private void initView() {
// TODO Auto-generated method stub
open = (Button) findViewById(R.id.open);
close = (Button) findViewById(R.id.close);
/**
* 开启火箭
*/
open.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startService(new Intent(MainActivity.this,RocketService.class));
finish();
}
});
/**
* 关闭火箭
*/
close.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
stopService(new Intent(MainActivity.this,RocketService.class));
finish();
}
});
}
}
2、RocketService 火箭服务类
该类主要是实现小火箭挂载在屏幕窗体
实现屏幕随意拖拽
拖拽到指定位置自动发射
贴代码:
/**
*结合1、2、3.顺序看 注释比较详细
*/
public class RocketService extends Service {
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
private WindowManager mWM;
private int height;
private int width;
private View viewToast;
private ImageView iv_rocket;
private AnimationDrawable drawable;
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
//获取屏幕窗体
mWM = (WindowManager) getSystemService(WINDOW_SERVICE);
//获取屏幕宽高
height = mWM.getDefaultDisplay().getHeight();
width = mWM.getDefaultDisplay().getWidth();
//开启火箭
showRocket();
}
/**
* 开启小火箭
*/
private void showRocket() {
//1、让小火箭默认在左上角显示
final WindowManager.LayoutParams params = mParams;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
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_PHONE;
params.setTitle("Toast");
//指定吐司的所在位置(将吐司指定在左上角)
params.gravity = Gravity.LEFT+Gravity.TOP;
//2、 定义吐司layout布局 -填充给 >view挂载到屏幕上显示
viewToast = View.inflate(this, R.layout.rocket_view, null);
iv_rocket = (ImageView) viewToast.findViewById(R.id.iv_rocket);
//拿到动画的额帧
drawable = (AnimationDrawable) iv_rocket.getBackground();
//iv_rocket.startAnimation(drawable);
//获取背景图片后,让其动起来
drawable.start();
//3、图片手指拖动到额监听事件
iv_rocket.setOnTouchListener(new OnTouchListener() {
//开始的 x y 坐标
private int startX;
private int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//获取按下的xy坐标
startX = (int) event.getRawX();
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//获取移动xy坐标和按下的xy坐标做差,做差得到的值小火箭移动的距离
//移动过程中做容错处理
//第一次移动到的位置,作为第二次移动的初始位置
int moveX = (int) event.getRawX();
int moveY = (int) event.getRawY();
//做差拿到移动距离
int disX = moveX - startX;
int disY = moveY - startY;
//将按下的坐标+移动距离 = 当前位置重新赋值给窗体
params.x = params.x+disX;
params.y = params.y+disY;
//在窗体中仅仅告知吐司的左上角的坐标
if(params.x<0){
params.x = 0;
}
if(params.y<0){
params.y = 0;
}
if(params.x>width-viewToast.getWidth()){
params.x = width-viewToast.getWidth();
}
if(params.y>height-22-viewToast.getHeight()){
params.y = height-22-viewToast.getHeight();
}
//告知吐司在窗体上刷新
mWM.updateViewLayout(viewToast, params);
//在第一次移动完成后,将最终坐标作为第二次移动的起始坐标
startX = (int) event.getRawX();
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
//手指放开的时候,如果放手坐标,则指定区域内
if(params.x>200 && params.x<300 && params.y>300){
//火箭的发射
sendRocket();
//在开启火箭过程中,去开启一个新的activity,activity透明,在此activity中放置两张图片(淡入淡出效果)
Intent intent = new Intent(getApplicationContext(),BackgroundActivity.class);
//指定开启新的activity任务栈
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
break;
}
return true;
}
});
//4、将自定义的tosat布局添加到窗体管理器中
mWM.addView(viewToast, params);
}
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
mParams.y = (Integer) msg.obj;
//更新到火箭上(窗体)
mWM.updateViewLayout(viewToast, mParams);
};
};
private void sendRocket() {
new Thread(){
public void run() {
for(int i=0;i<11;i++){
int y = 350 - i*35;//350 是当前模拟器高
//睡眠
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
//通过消息机制,将y轴坐标作为主线程火箭竖直方向上的显示位置
Message msg = Message.obtain();
msg.obj = y;
handler.sendMessage(msg);
}
};
}.start();
}
@Override
public void onDestroy() {
if(mWM!=null && viewToast!=null){
mWM.removeView(viewToast);
}
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
3、BackgroundActivity 小火箭尾气
该类完成小火箭发射尾气动画的实现
代码不多 主要就是一个淡入淡出的动画
public class BackgroundActivity extends Activity {
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
//结束此activity,销毁尾气图片
finish();
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置尾气图片
setContentView(R.layout.activity_background);
ImageView iv_top = (ImageView) findViewById(R.id.iv_top);
ImageView iv_bottom = (ImageView) findViewById(R.id.iv_bottom);
//尾气淡入淡出效果,动画是异步操作,并不会去阻塞主线程
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(500);
iv_top.startAnimation(alphaAnimation);
iv_bottom.startAnimation(alphaAnimation);
//将尾气消失,发送一个延时消息,1秒以后结束此activity,
mHandler.sendEmptyMessageDelayed(0, 1000);
}
}
清单文件中的注册需要加一个主题:
<activity
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:name="com.example.demo2_rocket.BackgroundActivity"/>
xml布局
<?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/iv_bottom"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/desktop_smoke_m"/>
<ImageView
android:id="@+id/iv_top"
android:layout_above="@id/iv_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/desktop_smoke_t"/>
</RelativeLayout>
动画rocket_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/desktop_rocket_launch_1"
android:duration="200"/>
<item android:drawable="@drawable/desktop_rocket_launch_2"
android:duration="200"/>
</animation-list>
好了 完成了,就2个activity 、一个services,看代码注释完全可以看明白