首页 > 代码库 > 仿腾讯手机管家火箭发射

仿腾讯手机管家火箭发射

好久没有写过博客了,前段时间一个项目中用到了浮点(漂浮在窗体上),于是突发灵感发现可以实现类似于腾讯手机管家火箭升空效果

    实现步骤:1:新建一个类 名为RocketView(用来显示浮点,当手指拖动浮点变成火箭图标)

                        2:新建一个类 名LaunchView(火箭发射台,当手指拖动RocketView浮点到指定位置释放手指后 火箭深空)

                        3:在activity中调用RocketView的显示浮点方法进行演示

                        4:总结

1:新建一个类 名为RocketView(用来显示浮点,当手指拖动浮点变成火箭图标)

package com.masa.rocketlaunch;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;

/**
 * author:janecer 
 * email:jiangxiaocai@youline.com.cn
 * 2014年10月22日  下午3:41:59
 * 类说明 
 */
public class RocketView  extends FrameLayout{

	private static final String TAG = null;
	private static final  int ROCKET_SENDING=10;
	private static final int ROCKET_SENDED=11;
	private static final int VIBRATE=12;
	private static final String FLOAT_MARK="float_mark";
	private WindowManager wm;
	private WindowManager.LayoutParams wlp;
	private TextView tv_rocket;
	private Context ctx;
	private int statusBar;//状态栏高度
	private LaunchView launchView;
	
	private float x;
	private float y;
	
	//在拖到 发射台发射之前 几下浮点的位置,以便发射完后  把浮点设置到这个位置
	private float x_o;
	private float y_o;
	
	private float xInScrren;
	private float yInScrren;
	
	private Vibrator vibrator;
	private boolean isVibrator=false;
	
	private int rocket_height;//火箭的高度
	/**
	 * 手机屏幕的宽度和高度
	 */
	private int s_width;
	private int s_height;
	
	/**
	 * 判断火箭是否在飞行中,如果在飞行中,避免手指再次出破屏幕
	 */
	private boolean isFlying=false;
	
	//发射火箭 
	private Handler handler=new Handler(){
		public void handleMessage(android.os.Message msg) {
		     switch (msg.what) {
			    case ROCKET_SENDING://发射火箭
				     updatePosition();
	       			break;
			    case ROCKET_SENDED://火箭发射完成
			    	launchView.removeView();
			    	launchView.setBackgroundResource(R.drawable.rocket_base);
			    	isFlying=false;
			    	setImage(false, false);
			    	xInScrren=x_o;
			    	yInScrren=y_o;
			    	
			    	updatePosition();
			    	break;
			    case VIBRATE:
			    	vibrator.vibrate(msg.arg1);
			    	break;
			} 	
		};
	};
	
	public RocketView(Context context) {
		this(context, null);
	}
	
	public RocketView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}
	
	public RocketView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		
		this.ctx=context;
		
		//初始化屏幕的宽度和高度
		this.s_height=DimensionUtil.getHeight(context);
		this.s_width=DimensionUtil.getWidth(context);
		
		//给本布局设置 长度和高度
		ViewGroup.LayoutParams vlp=new ViewGroup.LayoutParams(-2,-2);
		this.setLayoutParams(vlp);
		this.setBackgroundColor(Color.TRANSPARENT);
		
		//初始化状态栏高度
		if(context instanceof Activity){
			initStatusBar((Activity)context);
		}
		vibrator=(Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
		wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		wlp=new WindowManager.LayoutParams();
		
		
		//给显示浮点的ImaView初始化 
		tv_rocket=new TextView(context);
		tv_rocket.setGravity(Gravity.CENTER);
		FrameLayout.LayoutParams flp=new FrameLayout.LayoutParams(-2,-2);
		tv_rocket.setLayoutParams(flp);
		
		
		setImage(false,false);
        this.addView(tv_rocket);
        Log.i(TAG, "RocketView:___>");
	}
	
	/**
	 * 设置发射台的window
	 * @param lv
	 */
	public void setLaunchView(LaunchView lv){
		this.launchView=lv;
	}
	/**
	 * 用来设置 图标是火箭图标 还是 圆形图标
	 * @param isRocket   
	 * @param isRelease  true表示 正在深空的火箭  
	 */
	public void setImage(boolean isRocket,boolean isRelease){
		if(isRocket){
			tv_rocket.setText("");
			tv_rocket.setBackgroundResource(isRelease?R.drawable.rocket_release:R.drawable.rocket_unrelease);
		}else{
			//设置圆形图标
			tv_rocket.setBackgroundResource(R.drawable.float_);
			
	        tv_rocket.setText(((Util.getUsefoMe(ctx)*100)/Util.getTotalMe())+"%");
		}
//		wlp.width = -2;
//		wlp.height =-2;
//		wm.updateViewLayout(this, wlp);
	}

	public void addToWindow(){
		wlp.width =  -2;
		wlp.height = -2;
		wlp.format=PixelFormat.RGBA_8888;
		wlp.type=WindowManager.LayoutParams.TYPE_PHONE;
		wlp.flags=WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		
		wlp.gravity=Gravity.LEFT|Gravity.TOP;
		wlp.x=DimensionUtil.getWidth(ctx)/2;
		wlp.y=(DimensionUtil.getHeight(ctx)-statusBar)/2;
//      wlp.alpha=0.5f;
		wm.addView(this,wlp);
	}
	
	public void removeViewFromWindow(){
		wm.removeView(this);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		
		if(!isFlying){
		switch (ev.getAction()) {
		    case MotionEvent.ACTION_DOWN:
		    	x_o=ev.getRawX();
		    	y_o=ev.getRawY();
		    	
		    	this.x=ev.getX();
		    	this.y=ev.getY();
		    	setImage(true,false);
		    	launchView.addToWindow();
			    break;
		    case MotionEvent.ACTION_MOVE:
		    	this.xInScrren= ev.getRawX();
		    	this.yInScrren= ev.getRawY();
		    	updatePosition();
		    	//Log.i(TAG,"this.x:"+this.x+"   this.y:"+this.y);
		    	if(xInScrren>launchView.x-launchView.r&&xInScrren<launchView.x+launchView.r&&yInScrren>launchView.y-launchView.r&&yInScrren<launchView.y+launchView.r){
		    		//显示需要发射的火焰
		    		Log.i(TAG, "显示发射火焰");
		    		launchView.isShowFire(true);
		    		isVibrator=true;
		    		new Thread(){
		    			public void run() {
		    				while (isVibrator) {
		    					Message msg=Message.obtain();
		    					msg.arg1=(int) Math.round(Math.random() * 100+200);
		    					msg.what=VIBRATE;
								handler.sendMessage(msg);
								try {
									Thread.currentThread().sleep(msg.arg1);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
		    			};
		    			
		    		}.start();
		    	}else{
		    		vibrator.cancel();
		    		isVibrator=false;
		    		launchView.isShowFire(false);
		    	}
		    	break;
		    case MotionEvent.ACTION_UP:
		    	
		    	isVibrator=false;
		    	//根据火焰是否显示 决定是否发射火箭
		    	if(launchView.ivfire.getVisibility()==View.VISIBLE){
		    		//发射火箭
		    		Log.i(TAG, "发射火箭逻辑");
		    		launchView.ivfire.setVisibility(View.GONE);
		    		launchView.setBackgroundResource(R.drawable.smoke_m);
		    		setImage(true,true);
		    		isFlying=true;
		    		new Thread(){
		    			public void run() {
		    				int height=tv_rocket.getHeight();
		    				Log.i(TAG, "火箭的高度:"+height);
		    				 while (yInScrren>0) {
								handler.sendEmptyMessage(ROCKET_SENDING);
								try {
									Thread.currentThread().sleep(1);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
								yInScrren-=2;
		 					 }
		    				 handler.sendEmptyMessage(ROCKET_SENDED);
		    			};
		    		}.start();
		    		 
		    	}else{
		    		setImage(false,true);
		    		if(!isFlying){
		    			launchView.removeView();
		    		}
		    	}
		    	break;
		}}
		return super.onTouchEvent(ev);
	}
	
	public void updatePosition(){
		wlp.x=(int) (this.xInScrren-this.x);
		wlp.y=(int) (this.yInScrren-this.y-statusBar);
		wm.updateViewLayout(this,wlp);
	}
	
	/**
	 * 初始化状态栏高度
	 * @param act
	 */
	public void initStatusBar(Activity act){
         if(act.getWindow().getAttributes().flags==WindowManager.LayoutParams.FLAG_FULLSCREEN){
        	 statusBar=0;
         }else{
        	 try {
				Class<?> clazz=Class.forName("com.android.internal.R$dimen");
				Object obj=clazz.newInstance();
				int j = Integer.parseInt(clazz.getField("status_bar_height").get(obj).toString());
				statusBar = act.getResources().getDimensionPixelSize(j);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
         }			
	}
}


2:新建一个类 名LaunchView(火箭发射台,当手指拖动RocketView浮点到指定位置释放手指后 火箭深空)

package com.masa.rocketlaunch;

import java.text.Format;

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;

/**
 * author:janecer 
 * email:jiangxiaocai@youline.com.cn
 * 2014年10月23日  下午2:08:55
 * 类说明   火箭发射台
 */
public class LaunchView extends RelativeLayout{

	
	private static final String TAG = LaunchView.class.getSimpleName();
	private WindowManager wm;
	private WindowManager.LayoutParams wlp;
	
	private Context ctx;
	
	public int x;//发射台的x坐标
	public int y;//发射台的y坐标
	public int r;//待中心点的半径
	
	
	private Handler handler=new Handler(){
		public void handleMessage(android.os.Message msg) {
		    
		 	
		};
	};
	public ImageView ivfire;
	
	
	public LaunchView(Context context) {
		this(context, null);
	}
	
	public LaunchView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}
	
	
	public LaunchView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		ctx=context;
		
		wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		wlp=new WindowManager.LayoutParams();
		
		
		
		ViewGroup.LayoutParams vlp=new ViewGroup.LayoutParams(-1,DimensionUtil.dip2px(context, 108));
		this.setLayoutParams(vlp);
		this.setBackgroundResource(R.drawable.rocket_base);
		
		ivfire = new ImageView(context);
		ivfire.setScaleType(ScaleType.FIT_XY);
		setImageFire();
		RelativeLayout.LayoutParams rlp=new RelativeLayout.LayoutParams((int) (DimensionUtil.getWidth(context)/4.5)*2,(int) (DimensionUtil.getWidth(context)/4.5));
		rlp.addRule(CENTER_IN_PARENT);
		this.addView(ivfire, rlp);
		
		r=(int) (DimensionUtil.getWidth(context)/4.5);
		x=DimensionUtil.getWidth(context)/2;
		y=DimensionUtil.getHeight(context)-r;
		Log.i(TAG, "x:"+x+"   y:"+y+"   r:"+r);
	}
	
	public void setImageFire( ){
		ivfire.setBackgroundResource(R.drawable.rocket_fire1);
	}
	
	public void isShowFire(boolean isshow){
		ivfire.setVisibility(isshow?View.VISIBLE:View.GONE);
	}
	
	public void addToWindow(){
		wlp.flags=WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		wlp.type=WindowManager.LayoutParams.TYPE_PHONE;
		wlp.gravity=Gravity.LEFT|Gravity.TOP;
		wlp.format=PixelFormat.RGBA_8888;
		
		wlp.width=this.getLayoutParams().width;
		wlp.height=this.getLayoutParams().height;
		
		wlp.x=0;
		wlp.y=DimensionUtil.getHeight(ctx);
		wm.addView(this,wlp);
	}
	
	
	public void removeView(){
		wm.removeView(this);
	}
}


3:在activity中调用RocketView的显示浮点方法进行演示


	    RocketView rocketView=new RocketView(this.getApplicationContext());
	    rocketView.setLaunchView(new LaunchView(this.getApplicationContext()));
	    rocketView.addToWindow();

4:总结

         浮点的实现主要使用到android api的WindowManager,以及对WIndowManager.LayoutParams的一些参数的熟悉。
         
作者能力有限,特别是设计模式方面 不是很懂,希望高手多多指点



         


仿腾讯手机管家火箭发射