package com.itheima52.rocket; import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.drawable.AnimationDrawable; import android.os.Handler; import android.os.IBinder; import android.os.Message; 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; /* * 主界面开启一个服务 startService(new Intent(this, RocketService.class)); finish(); stopService(new Intent(this, RocketService.class)); finish(); */ public class RocketService extends Service { private WindowManager.LayoutParams params; private int winWidth; private int winHeight; private WindowManager mWM; private View view; private int startX; private int startY; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); mWM = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);//WindowManager可以在手机屏幕上显示,而不用依赖于某个activity布局文件。 // 获取屏幕宽高 winWidth = mWM.getDefaultDisplay().getWidth(); winHeight = mWM.getDefaultDisplay().getHeight(); params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; params.type = WindowManager.LayoutParams.TYPE_PHONE;// 电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。 params.gravity = Gravity.LEFT + Gravity.TOP;// 将重心位置设置为左上方, // 也就是(0,0)从左上方开始,而不是默认的重心位置 params.setTitle("Toast"); view = View.inflate(this, R.layout.rocket, null);// 初始化火箭布局 // 初始化火箭帧动画 ImageView ivRocket = (ImageView) view.findViewById(R.id.iv_rocket); /*iv_rocket.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/iv_rocket" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/desktop_rocket_launch_1" /> 火箭图片 </LinearLayout>*/ //火箭冒火帧动画,火苗一直闪烁, ivRocket.setBackgroundResource(R.drawable.anim_rocket); /* anim_rocket.xml <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" > 2张图片切换,200毫秒, <item android:drawable="@drawable/desktop_rocket_launch_1" android:duration="200"/> <item android:drawable="@drawable/desktop_rocket_launch_2" android:duration="200"/> </animation-list> */ AnimationDrawable anim = (AnimationDrawable) ivRocket.getBackground(); anim.start(); mWM.addView(view, params); view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 初始化起点坐标 startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int endX = (int) event.getRawX(); int endY = (int) event.getRawY(); // 计算移动偏移量 int dx = endX - startX; int dy = endY - startY; // 更新浮窗位置,WindowManager里面只能用params来移动 params.x += dx; params.y += dy; // 防止坐标偏离屏幕 if (params.x < 0) { params.x = 0; } if (params.y < 0) { params.y = 0; } // 防止坐标偏离屏幕 if (params.x > winWidth - view.getWidth()) { params.x = winWidth - view.getWidth(); } if (params.y > winHeight - view.getHeight()) { params.y = winHeight - view.getHeight(); } // System.out.println("x:" + params.x + ";y:" + params.y); mWM.updateViewLayout(view, params); // 重新初始化起点坐标 startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: if (params.x > 100 && params.x < 250 && params.y > winHeight - 120) { System.out.println("发射火箭!!!"); sendRocket(); // 启动烟雾效果,启动一个Activity,盖住下面的Activity,使得下面的不能点击。 Intent intent = new Intent(RocketService.this,BackgroundActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 通过Service启动Activity,Service不用栈,因此要先启动一个栈来存放activity startActivity(intent); } break; default: break; } return true; } }); } private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { // 更新火箭位置 int y = msg.arg1; params.y = y; mWM.updateViewLayout(view, params); }; }; /** * 发射火箭 */ protected void sendRocket() { // 设置火箭居中发射 params.x = winWidth / 2 - view.getWidth() / 2; mWM.updateViewLayout(view, params); new Thread() { @Override public void run() { int pos = 380;// 移动总距离 for (int i = 0; i <= 10; i++) {//移动10次,就移动到顶部了。 // 等待一段时间再更新位置,用于控制火箭速度 try { Thread.sleep(50);//主线程睡眠会让主线程很卡,因此要用子线城。 } catch (InterruptedException e) { e.printStackTrace(); } int y = pos - 38 * i; Message msg = Message.obtain();//不能在子线城更新界面 msg.arg1 = y; mHandler.sendMessage(msg); } } }.start(); } @Override public void onDestroy() { super.onDestroy(); if (mWM != null && view != null) { mWM.removeView(view); view = null; } } }
package com.itheima52.rocket; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.animation.AlphaAnimation; import android.widget.ImageView; /** * 烟雾背景 */ public class BackgroundActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bg); /* activity_bg.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_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:src="@drawable/desktop_smoke_m" /> 底下的大烟图片 <ImageView android:id="@+id/iv_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/iv_bottom" android:layout_alignParentLeft="true" android:src="@drawable/desktop_smoke_t" /> 中间的细长的烟 </RelativeLayout>*/ ImageView ivTop = (ImageView) findViewById(R.id.iv_top); ImageView ivBottom = (ImageView) findViewById(R.id.iv_bottom); // 渐变动画 AlphaAnimation anim = new AlphaAnimation(0, 1); anim.setDuration(1000); anim.setFillAfter(true);// 动画结束后保持状态 // 运行动画 ivTop.startAnimation(anim); ivBottom.startAnimation(anim); new Handler().postDelayed(new Runnable() {//Handler可以发message也可以发Runnable @Override public void run() { finish(); } }, 1000);// 延时1秒后结束activity,不能直接调用finish,因为动画要执行1秒钟。 } }
activity的启动模式: 1.Standard:启动A,然后A启动B,B再启动A。 2.SingleTask:首先启动A,A启动B,B启动C,C启动A的时候把B,C干掉,也就是栈里面只能有一个A. 3.SingleTop:启动A,A启动B,B启动C,C再启动C时不会创建新的C而是用原来的C,因为顶上只能有一个C. 4.SingleInstance:只有一个A,不如许别的进来.