悬浮窗口WindowManager

安卓中Activity,Dialog,Toast等视图都是附在Window上的,Window是View的直接管理者

		final WindowManager windowManager = (WindowManager)
				getSystemService(Context.WINDOW_SERVICE);// "window"
		final WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();
		
		//若不设置gravity ,并且不设置windowParams.x和windowParams.y,则默认位于屏幕中除去通知栏以外部分的中间位置
		//若设置为windowParams.gravity = Gravity.RIGHT|Gravity.TOP;并且不设置windowParams.x和windowParams.y
		//则位于屏幕除通知栏以外的左上角
		
		//windowParams.x和windowParams.y的是偏移量
		//由于没有设置windowParams.gravity,所以下面的设置会看到新窗口位于中央(屏幕中除去通知栏以外部分的中央)偏右100像
		//素,偏上200像素处,若x或y超出了屏幕中除去通知栏以外部分,则新窗口也会位于边沿而不会一块在里面一块在外面
		
		windowParams.x=100;
		windowParams.y=-200;
		// 设置宽和高
		windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
		windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
		//当前Window区域以外的事件会交给下层Window,当前Window区域以内的事件自己处理,通常会设置这个属性,否则其他Window无法收到单击事件
		windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

		windowParams.format = PixelFormat.TRANSLUCENT;
		windowParams.windowAnimations = 0;
		//透明度
		windowParams.alpha=0.3f;
		final ImageView iv=new ImageView(getApplicationContext()){
			float startLayoutX,startLayoutY,startTouchX,startTouchY;
			@Override
			public boolean onTouchEvent(MotionEvent event) {
				/*windowParams.x和windowParams.y是偏移量,所以要记录一开始的触摸位置和窗口位置,
				 * 
				 */
				if (event.getAction()==MotionEvent.ACTION_DOWN) {
					startLayoutX=windowParams.x;
					startLayoutY=windowParams.y;
					
					startTouchX=event.getRawX();
					startTouchY=event.getRawY();
					
				}
				float x=event.getRawX();
				float y=event.getRawY();
				
				//当前位置和按下的位置的差值为偏移量,把该偏移量加到按下时的偏移量上作为窗口新的位置
				windowParams.x=  (int) (startLayoutX+(x-startTouchX))  ;
				windowParams.y=(int) (startLayoutY+(y-startTouchY));
				
				//更新位置
				windowManager.updateViewLayout(this, windowParams);
				return true;
			}
		};

		iv.setImageResource(R.drawable.ic_launcher);
		iv.setBackgroundColor(Color.BLUE);
		
		windowManager.addView(iv, windowParams);
		



不管怎么拖动都不会超出屏幕边界



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用 JetPack Compose 编写悬浮窗的示例代码: ``` @Composable fun FloatingWindow() { val windowParams = remember { WindowManager.LayoutParams().apply { type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN format = PixelFormat.TRANSLUCENT gravity = Gravity.TOP or Gravity.START width = 200.dp.toPx() height = 200.dp.toPx() x = 0 y = 0 } } val windowManager = LocalWindowManager.current val density = LocalDensity.current var offsetX by remember { mutableStateOf(0f) } var offsetY by remember { mutableStateOf(0f) } var isDragging by remember { mutableStateOf(false) } Box( Modifier .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) } .background(Color.White, RoundedCornerShape(8.dp)) .pointerInput(Unit) { forEachGesture { awaitPointerEventScope { val down = awaitFirstDown() isDragging = true val position = down.position val density = LocalDensity.current val offsetXStart = with(density) { position.x.toDp() } val offsetYStart = with(density) { position.y.toDp() } val startX = offsetX val startY = offsetY val touchSlop = with(density) { 8.dp.toPx() } drag(down.id) { val dx = it.positionChange().x val dy = it.positionChange().y if (sqrt(dx * dx + dy * dy) > touchSlop) { offsetX = startX + dx offsetY = startY + dy } } isDragging = false } } } ) { Text( "Hello, World!", Modifier.padding(16.dp), color = Color.Black, fontSize = 16.sp ) } LaunchedEffect(windowManager) { windowManager.addView( AndroidView( factory = { context -> AndroidView(context).apply { layoutParams = windowParams } }, update = { view -> view.setContent { Box( Modifier .fillMaxSize() .background(Color.Transparent) ) { if (!isDragging) { windowParams.x = offsetX.roundToInt() windowParams.y = offsetY.roundToInt() windowManager.updateViewLayout(view, windowParams) } this@Box.setContent(this) } } } ) ) } } ``` 这个示例代码使用 `WindowManager` 创建了一个悬浮窗,并使用 `JetPack Compose` 实现了拖拽功能。你可以根据自己的需求修改代码,比如更改悬浮窗的大小、位置等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值