android应用程中添加悬浮框

本文深入解析了Android悬浮窗服务的实现原理,通过实例代码展示了如何使用Service和WindowManager来创建和管理始终出现在屏幕上方的悬浮窗。文章详细介绍了悬浮窗的创建过程、布局参数设置、触摸事件处理以及与主程序的交互,旨在帮助开发者掌握悬浮窗的高级用法。
摘要由CSDN通过智能技术生成

先说明下项目需求:在项目中添加一个浮动按钮,始终出现在屏幕上方,可以获得点击事件,当程序启动时,悬浮框出现,直到程序退出,悬浮框消失。

思路:service是android中的后台组件,可以理解为一个没有窗口的activity,可以一直运行在整个应用程序中,因此,在service中添加窗口,并在程序启动时,启动service,程序结束时,关闭service,就可以满足项目需求

实现方式:service+windowManager

代码如下:

public class FloatService extends Service {

	WindowManager wm = null;
	WindowManager.LayoutParams wmParams = null;
	View view;
	private float mTouchStartX;
	private float mTouchStartY;
	private float x;
	private float y;
	int state;
	ImageView iv;
	private float StartX;
	private float StartY;
	int delaytime=1000;
	private boolean flag = false;
	private TextView mTvNum;
	private MessageTableDao tableDao;
	@Override
	public void onCreate() {
		Log.d("FloatService", "onCreate");
		super.onCreate();
		view = LayoutInflater.from(this).inflate(R.layout.floating, null);
		iv = (ImageView) view.findViewById(R.id.img1);
		mTvNum = (TextView) view.findViewById(R.id.tv_num);
		tableDao = new MessageTableDao(new MyDataBaseHeliper(FloatService.this));
		int num = tableDao.getAllUnreadContentCount();
		if (num == 0) {
			mTvNum.setVisibility(View.GONE);
		}else {
			mTvNum.setText(num+"");
		}
		
//		iv.setVisibility(View.GONE);
		createView();
//		handler.postDelayed(task, delaytime);
	}

	private void createView() {
		SharedPreferences shared = getSharedPreferences("float_flag",
				Activity.MODE_PRIVATE);
		SharedPreferences.Editor editor = shared.edit();
		editor.putInt("float", 1);
		editor.commit();
		// 获取WindowManager
		wm = (WindowManager) getApplicationContext().getSystemService("window");
		// 设置LayoutParams(全局变量)相关参数
		wmParams = ((DemoMyApplication) getApplication()).getMywmParams();
		wmParams.type = 2002;
//		wmParams.type = 1003;
		wmParams.flags |= 8;
		wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角
		// 以屏幕左上角为原点,设置x、y初始值
		wmParams.x = 0;
		wmParams.y = 140;
		// 设置悬浮窗口长宽数据
		wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
		wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
		wmParams.format = 1;
		
		wm.addView(view, wmParams);

		view.setOnTouchListener(new OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				// 获取相对屏幕的坐标,即以屏幕左上角为原点
				x = event.getRawX();
				y = event.getRawY() - 25; // 25是系统状态栏的高度
				Log.i("currP", "currX" + x + "====currY" + y);// 调试信息
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					state = MotionEvent.ACTION_DOWN;
					flag = true;
					StartX = x;
					StartY = y;
					// 获取相对View的坐标,即以此View左上角为原点
					mTouchStartX = event.getX();
					mTouchStartY = event.getY();
					Log.i("startP", "startX" + mTouchStartX + "====startY"
							+ mTouchStartY);// 调试信息
					break;
				case MotionEvent.ACTION_MOVE:
					state = MotionEvent.ACTION_MOVE;
					flag = false;
					
					moveView();
//					updateViewPosition();
					break;

				case MotionEvent.ACTION_UP:
					state = MotionEvent.ACTION_UP;

					System.out.println("*****action up****");
					updateViewPosition();
					if (flag) {
						Message msg = handler.obtainMessage(100);
						handler.sendMessage(msg);
					}
//					showImg();
					mTouchStartX = mTouchStartY = 0;
					break;
				}
				return true;
			}
		});

//		iv.setOnClickListener(new OnClickListener() {
//			@Override
//			public void onClick(View v) {
//				System.out.println("*****click****");
//				// TODO Auto-generated method stub
				Intent serviceStop = new Intent();
				serviceStop.setClass(FloatService.this, FloatService.class);
				stopService(serviceStop);
//			}
//		});

	}

	public void showImg() {
		if (Math.abs(x - StartX) < 1.5 && Math.abs(y - StartY) < 1.5
				&& !iv.isShown()) {
			iv.setVisibility(View.VISIBLE);
		} else if (iv.isShown()) {
			iv.setVisibility(View.GONE);
		}
	}

	public void moveView() {
		System.out.println("Math.abs(x - StartX) = "+Math.abs(x - StartX)+"  Math.abs(y - StartY) = "+Math.abs(y - StartY));
		if (Math.abs(x - StartX) < 1.5 && Math.abs(y - StartY) < 1.5) {
			flag = true;
//			iv.setVisibility(View.VISIBLE);
		} else {
			updateViewPosition();
//			iv.setVisibility(View.GONE);
		}
	}
	
	private Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 100:
				if (!TBConstant.KIND.equals("0") ) {
					Intent friends= NavigationController.setRootIntent(FloatService.this, FriendTabActivity.class);
					friends.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					startActivity(friends);
				}else {

					Intent intentdialog = new Intent(FloatService.this,AddNoticeDialogActivity.class);
					intentdialog.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					startActivity(intentdialog);

				}

				break;

			default:
				break;
			}
		};
	};
//	private Runnable task = new Runnable() {
//		public void run() {
//			// TODO Auto-generated method stub
			dataRefresh();
//			handler.postDelayed(this, delaytime);
//			wm.updateViewLayout(view, wmParams);
//		}
//	};

//	public void dataRefresh() {
//		tx.setText("" + memInfo.getmem_UNUSED(this) + "KB");
//		tx1.setText("" + memInfo.getmem_TOLAL() + "KB");
//	}

	private void updateViewPosition() {
		// 更新浮动窗口位置参数
		wmParams.x = (int) (x - mTouchStartX);
		wmParams.y = (int) (y - mTouchStartY);
		wm.updateViewLayout(view, wmParams);
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d("FloatService", "onStart");
//		setForeground(true);
		super.onStart(intent, startId);
	}

	@Override
	public void onDestroy() {
//		handler.removeCallbacks(task);
		Log.d("FloatService", "onDestroy");
		wm.removeView(view);
		super.onDestroy();
	}

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

说明:这段代码是我项目中一个实现悬浮框的类,没有整理,主要实现在creatView()方法中,这个方法是有缺陷,我没有找到合适解决办法,不过还在寻找中·······



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值