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

来源:互联网 发布:软件著作权作者几个 编辑:程序博客网 时间:2024/04/28 05:46

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

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

<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;@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic 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;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();customView = new CustomView(getApplicationContext());}@Overridepublic 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");}@Overridepublic 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;}// # 返回truereturn 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


0 0