zoukankan      html  css  js  c++  java
  • 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上下载源代码。

  • 相关阅读:
    AI零基础入门之人工智能开启新时代—下篇
    AI零基础入门之人工智能开启新时代—上篇
    Markdown 快速入门
    Linux GCC/G++ 基础(1) 之
    解决 Ubuntu 下使用 sublime text 3 无法输入中文
    WPF:界面布局之- TaiChi
    常用命令之- touch
    微软net平台是不是快完了?看了一天智联招聘,现在连传统的网站或系统平台都不怎么用net了
    蓝牙Ble开发(支持API18<Android 4.3 Jelly>及以上)
    Android系统休眠对程序的影响以及处理
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299630.html
Copyright © 2011-2022 走看看