悬浮框,View置顶

今天写了个小demo,主要功能:从A应用打开B应用,打开B只会弹出一个View提示。

其实当时想到,其他的App又不是我写的,我怎么能弹出View呢。后来想想也不难只是我的思路错了。

主要就是获取WindowManager就好了大笑


发个图,打开了一个叫"萤Wifi的软件",UI很丑,不要吐槽啊,功能能看就好了


权限别拉下了:

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


代码如下


package com.example.dialogdemo;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;

public class MainActivity extends Activity {
	private String pkg = "XXXXXXXXXXX"; //应用包名
	private String TAG = "MainActivity";

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

			@Override
			public void onClick(View v) {
				startApp(MainActivity.this, pkg);
				new MyThread().run();
			}
		});
	}

	private class MyThread extends Thread {
		@Override
		public void run() {
			super.run();
			try {
				Thread.sleep(4 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			creatDialog();
		}
	}

	private void creatDialog() {
		// 创建LayoutParams
		WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();

		// 设置窗口的类型
		layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;

		// 设置行为选项
		layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

		// 设置透明度
		layoutParams.alpha = 80;

		layoutParams.gravity = Gravity.CENTER;

		// 设置宽高
		layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
		layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

		// 添加到View到窗口
		final WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
		// 创建需要添加的View
		final View view = LayoutInflater.from(this).inflate(R.layout.dialog_, null);
		view.findViewById(R.id.button1).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				windowManager.removeView(view);
			}
		});

		windowManager.addView(view, layoutParams);
	}

	/**
	 * 启动APP
	 * 
	 * @param context
	 * @param pkg
	 */
	public void startApp(Context context, String pkg) {
		try {
			Intent intent = context.getPackageManager().getLaunchIntentForPackage(pkg);
			context.startActivity(intent);
		} catch (ActivityNotFoundException e) {
			Log.e(TAG, "APP Error:" + e.getMessage());
		}catch (Exception e) {
			Log.e(TAG, "APP Error:" + e.getMessage());
		}

	}
}
就这样不发Demo了,这个很简单。好像小米不行,小米的设置里有个悬浮框显示或者不显示的设置,无力吐槽。

在 Android 和 iOS 平台上实现可拖拽的悬窗功能,分别需要遵循各自平台的开发规范,并处理好权限申请、手势识别以及界面层级管理等问题。 ### 在 Android 中实现可拖拽悬窗 1. **申请权限**: Android 应用需要在 `AndroidManifest.xml` 文件中声明系统级悬窗权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 此权限允许应用在其他应用之上绘制窗口内容[^4]。 2. **创建悬窗视图**: 使用 `WindowManager` 来添加一个自定义的 `View` 到屏幕上。该视图可以是一个简单的 `ImageView` 或者包含更多交互元素的布局。 3. **实现拖拽逻辑**: 通过 `OnTouchListener` 监听触摸事件,在 `ACTION_MOVE` 事件中不断更新悬窗的位置: ```java final WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); View floatingView = LayoutInflater.from(context).inflate(R.layout.floating_layout, null); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); windowManager.addView(floatingView, params); floatingView.setOnTouchListener(new View.OnTouchListener() { private int initialX; private int initialY; private float initialTouchX; private float initialTouchY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: initialX = params.x; initialY = params.y; initialTouchX = event.getRawX(); initialTouchY = event.getRawY(); return true; case MotionEvent.ACTION_MOVE: params.x = initialX + (int) (event.getRawX() - initialTouchX); params.y = initialY + (int) (event.getRawY() - initialTouchY); windowManager.updateViewLayout(v, params); return true; default: return false; } } }); ``` ### 在 iOS 中实现可拖拽悬窗 1. **创建动视图**: 在 iOS 中,可以通过将自定义视图添加到 `UIWindow` 的最上层来实现悬窗效果。 2. **实现拖动手势识别**: 使用 `UIPanGestureRecognizer` 来监听拖动手势,并实时更新动视图的位置: ```swift let floatingView = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: 60)) floatingView.backgroundColor = .systemBlue floatingView.layer.cornerRadius = 30 if let window = UIApplication.shared.windows.first { window.addSubview(floatingView) } let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) floatingView.addGestureRecognizer(panGesture) @objc func handlePan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: nil) if let view = gesture.view { view.center = CGPoint(x: view.center.x + translation.x, y: view.center.y + translation.y) } gesture.setTranslation(.zero, in: nil) } ``` 3. **持久化位置信息**: 可以使用 `UserDefaults` 来保存用户最后放置悬窗的位置,以便下次启动时恢复。 ### 注意事项 - 在 Android 上,由于涉及到系统级别的权限申请,部分设备可能需要用户手动开启权限。 - 在 iOS 上,悬窗不会像 Android 那样“始终置顶”,因为 iOS 对 UI 层级控制更为严格。 - 如果是微信小程序等跨平台框架,则需要结合原生组件和 JavaScript 桥接技术来实现类似效果,同时需要注意不同平台上的兼容性问题[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值