在某游戏中,一般都是一队4个人,但是在有的主播直播里,显示栏看上去是5个人,比如
这个是怎么弄的呢?
有2种方式,一个是在投屏的软件画面里拉一个小窗口进去,(PC端操作)
另外一个是在手机上显示一个悬浮窗,达到以假乱真的效果,
这里我们来看看悬浮窗的使用,主要是windowManager.addView方法来添加
如果需要拖动,更新坐标后调用 windowManager.updateViewLayout
在 Android 中实现悬浮窗功能,可以通过 WindowManager
和 TYPE_APPLICATION_OVERLAY
来实现。以下是一个简单的实现步骤:
1. 添加权限
在 AndroidManifest.xml
文件中添加悬浮窗权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
从 Android 6.0(API 级别 23)开始,SYSTEM_ALERT_WINDOW
是一个危险权限,需要动态申请。
2. 动态检查和请求悬浮窗权限
在 Android 6.0 及以上版本中,需要通过 Settings.canDrawOverlays()
方法检查是否已授予悬浮窗权限。如果没有权限,则引导用户到设置页面手动开启。
示例代码如下:
if (!Settings.canDrawOverlays(this)) {
// 如果没有权限,跳转到设置页面
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1000); // 请求码为 1000
} else {
// 已经有权限,可以创建悬浮窗
createFloatingWindow();
}
3. 创建悬浮窗
使用 WindowManager
将一个视图添加到窗口上。
以下是完整的代码示例:
Java 实现
public class FloatingWindowService extends Service {
private WindowManager windowManager;
private View floatingView;
@Override
public void onCreate() {
super.onCreate();
// 初始化 WindowManager
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
// 创建悬浮窗布局
floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window_layout, null);
// 设置悬浮窗参数
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);
// 设置初始位置
params.x = 0;
params.y = 0;
// 添加视图到窗口
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;
}
return false;
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (floatingView != null) {
windowManager.removeView(floatingView);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
4. 定义悬浮窗布局
在 res/layout
目录下创建一个 XML 文件,例如 floating_window_layout.xml
,定义悬浮窗的 UI。
示例:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_launcher_foreground" />
</FrameLayout>
5. 启动服务
通过启动 FloatingWindowService
来显示悬浮窗。
示例代码:
Intent serviceIntent = new Intent(this, FloatingWindowService.class);
startService(serviceIntent);
6. 注意事项
- 权限问题:确保在 Android 6.0 及以上版本中动态申请悬浮窗权限。
- 适配不同 API 版本:
- 在 Android 8.0(API 级别 26)及以上,
TYPE_PHONE
已被弃用,应使用TYPE_APPLICATION_OVERLAY
。 - 在 Android 7.1(API 级别 25)及以下,可以使用
TYPE_PHONE
。
- 在 Android 8.0(API 级别 26)及以上,
- 用户体验:悬浮窗可能会干扰用户操作,请谨慎设计,并提供关闭或隐藏的功能