使用WindowManager添加可拖动悬浮窗口到桌面

添加可拖动悬浮窗口到桌面

先说一下权限问题,一般权限比较容易忘记:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />


MainActivity.java

public class MainActivity extends Activity {

	private Button button1;
	private Button button2;
	private Context context;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		context = this;
		button1 = (Button) findViewById(R.id.button1);	
		button1.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(context, FloatButtonService.class);
				intent.setAction("1");
				startService(intent);
			}
		});
		button2 = (Button) findViewById(R.id.button2);
		button2.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(context, FloatButtonService.class);
				intent.setAction("0");
				startService(intent);
			}
		});
}

FloatButtonService.java

public class FloatButtonService extends Service {

	/** 悬浮窗口 */
	private CustomView customView;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		customView = new CustomView(getApplicationContext());
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		if(intent.getAction().equals("1")){
			//# 显示悬浮视图
			customView.createWinPop();
		}else{
			// # 移出悬浮视图
			customView.closeWinPop();
		}
		return super.onStartCommand(intent, flags, startId);
	}	
}

CustomView.java

import java.lang.reflect.Field;

import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class CustomView extends LinearLayout {

	/** 窗口管理器(用于更新小悬浮窗的位置) */
	private WindowManager winManager;

	/** 记录系统状态栏的高度 */
	private int statusBarHeight;

	/** 记录当前手指位置在屏幕上的横坐标值 */
	private float xInScreen;

	/** 记录当前手指位置在屏幕上的纵坐标值 */
	private float yInScreen;

	/** 记录手指按下时在屏幕上的横坐标的值 */
	private float xDownInScreen;

	/** 记录手指按下时在屏幕上的纵坐标的值 */
	private float yDownInScreen;

	/** 记录手指按下时在小悬浮窗的View上的横坐标的值 */
	private float xInView;

	/** 记录手指按下时在小悬浮窗的View上的纵坐标的值 */
	private float yInView;

	/** 悬浮窗的参数 */
	private WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();

	private String tag = "CustomView";

	public CustomView(Context context) {
		super(context);
		winManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		LayoutInflater.from(context).inflate(R.layout.custom_view, this);
		TextView textView1 = (TextView) findViewById(R.id.textView1);
		textView1.setText("hello");
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// #手指按下,记录数值就好(但是不能忽略状态栏)
			xInView = event.getX();
			yInView = event.getY();
			xDownInScreen = event.getRawX();
			yDownInScreen = event.getRawY() - getStatusBarHeight();
			xInScreen = event.getRawX();
			yInScreen = event.getRawY() - getStatusBarHeight();
			break;

		case MotionEvent.ACTION_MOVE:
			// #手指移动的时候,需要更新悬浮窗口的位置
			xInScreen = event.getRawX();
			yInScreen = event.getRawY() - getStatusBarHeight();
			updateViewPosition();
			break;
		case MotionEvent.ACTION_UP:
			// #手指抬起的时候,判断是不是按下事件
			if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {
				Toast.makeText(getContext(), "#Click Event is called",
						Toast.LENGTH_SHORT).show();
//				BackFuntion.getIns().back();
			}
			break;
		default:
			break;
		}
		// # 返回true
		return true;
	}

	/**
	 * 更新悬浮窗在设备屏幕上的位置
	 */
	private void updateViewPosition() {
		mParams.x = (int) (xInScreen - xInView);
		mParams.y = (int) (yInScreen - yInView);
		winManager.updateViewLayout(this, mParams);
	}

	/**
	 * @return 返回状态栏高度的像素值。
	 */
	private int getStatusBarHeight() {
		if (statusBarHeight == 0) {
			try {
				Class<?> c = Class.forName("com.android.internal.R$dimen");
				Object o = c.newInstance();
				Field field = c.getField("status_bar_height");
				int x = (Integer) field.get(o);
				statusBarHeight = getResources().getDimensionPixelSize(x);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return statusBarHeight;
	}

	/**
	 * 创建悬浮窗
	 */
	public void createWinPop() {
		Point outSize = new Point();
		winManager.getDefaultDisplay().getSize(outSize);
		int screenWidth = outSize.x;
		int screenHeight = outSize.y;
		// #新版SDK不建议使用下面getWidth和getHeight获取
		// int screenWidth = winManager.getDefaultDisplay().getWidth();
		// int screenHeight = winManager.getDefaultDisplay().getHeight();
		mParams.x = screenWidth / 2 - 100;
		mParams.y = screenHeight / 2 - 100;
		mParams.type = WindowManager.LayoutParams.TYPE_PHONE;
		mParams.format = PixelFormat.RGBA_8888;
		mParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
				| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		mParams.gravity = Gravity.LEFT | Gravity.TOP;
		mParams.width = 150;
		mParams.height = 50;
		try {
			winManager.addView(this, mParams);
		} catch (Exception e) {
			Log.e("MainActivity", "#e=" + e.toString());
			Toast.makeText(getContext(), "#已经存在了", Toast.LENGTH_LONG).show();
		}
	}

	/**
	 *  关闭悬浮窗
	 */
	public void closeWinPop() {
		try {
			winManager.removeView(this);
		} catch (Exception e) {
			Log.e("MainActivity", "#e=" + e.toString());
			Toast.makeText(getContext(), "#不存在", Toast.LENGTH_SHORT).show();
		}

	}

}


这样在桌面上就能看到一个可以拖拽的可以点击的类似360卫士的悬浮窗口。



在添加和移出悬浮窗口的时候,会抛出相应的异常,没有窗口存在的时候移出会异常,有窗口存在的时候还去创建,就会异常,都进行捕抓就好。

本文来自CSDN博客,转载请联系作者注明出处http://blog.csdn.net/dreamintheworld


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值