问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Android开发实战:悬浮窗高级技巧大揭秘

创作时间:
作者:
@小白创作中心

Android开发实战:悬浮窗高级技巧大揭秘

引用
CSDN
11
来源
1.
https://blog.csdn.net/m0_64561613/article/details/139056707
2.
https://blog.csdn.net/CJohn1994/article/details/119917581
3.
https://blog.csdn.net/xingchenxuanfeng/article/details/128626109
4.
https://blog.csdn.net/gitblog_00044/article/details/138701370
5.
https://www.sohu.com/a/846046801_121798711
6.
https://blog.csdn.net/qq_43358469/article/details/139964948
7.
https://blog.csdn.net/2401_84102689/article/details/137360364
8.
https://developer.aliyun.com/article/1604808
9.
https://cloud.tencent.com/developer/article/2449651
10.
https://juejin.cn/post/7462956526711472138
11.
https://www.cnblogs.com/xqxacm/p/18535258

在Android开发中,悬浮窗功能可以显著提升用户体验。本文将从基础实现到高级技巧,再到实战案例,全面解析Android悬浮窗的开发要点。

01

基础篇:悬浮窗基本实现原理

悬浮窗的实现主要依赖于两个核心组件:Service和WindowManager。

1. 创建悬浮窗服务

首先需要创建一个Service类,用于后台运行悬浮窗逻辑。在Service的onCreate()方法中,初始化WindowManager并加载悬浮窗布局。

public class FloatingWindowService extends Service {
    private WindowManager windowManager;
    private View floatingView;

    @Override
    public void onCreate() {
        super.onCreate();
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                70, // 宽
                70, // 高
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
                        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
                        WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );
        params.gravity = Gravity.TOP | Gravity.START;
        params.x = 0;
        params.y = 100;
        windowManager.addView(floatingView, params);
    }
}

2. 请求悬浮窗权限

由于悬浮窗涉及系统级操作,需要在AndroidManifest.xml中声明权限:

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

并在代码中检查和申请权限:

if (!Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE);
}
02

进阶篇:高级技巧分享

1. 多语言环境下的悬浮窗适配

当系统语言切换时,悬浮窗的布局和文本需要相应更新。可以通过监听ACTION_LOCALE_CHANGED广播来实现:

private BroadcastReceiver mLocaleBroadcastReceiver;
private void registerLocaleReceiver() {
    if (mLocaleBroadcastReceiver == null) {
        mLocaleBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                mTvWindowTitle.setText(mContext.getString(R.string.window_title));
            }
        };
        IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
        mContext.registerReceiver(mLocaleBroadcastReceiver, filter);
    }
}

同时需要注意文本方向和图片翻转问题,特别是对于从右到左书写的语言(如阿拉伯语):

mLayoutWindow.setLayoutDirection(isRtl() ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mTvWindowTitle.setTextDirection(isRtl() ? View.TEXT_DIRECTION_RTL : View.TEXT_DIRECTION_LTR);

2. 实现流畅的拖动功能

拖动功能是悬浮窗的重要特性。关键在于正确处理触摸事件,使用getRawX()getRawY()获取屏幕坐标:

binding.root.setOnTouchListener(new View.OnTouchListener() {
    float xDown, yDown;
    float interactorTranslationXWhenDown, interactorTranslationYWhenDown;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xDown = event.getRawX();
                yDown = event.getRawY();
                interactorTranslationXWhenDown = interactorTranslationX;
                interactorTranslationYWhenDown = interactorTranslationY;
                break;
            case MotionEvent.ACTION_MOVE:
                float dx = event.getRawX() - xDown;
                float dy = event.getRawY() - yDown;
                interactorTranslationX = interactorTranslationXWhenDown + dx;
                interactorTranslationY = interactorTranslationYWhenDown + dy;
                updateTranslation();
                break;
        }
        return false;
    }
});
03

实战篇:FloatWindow开源项目解析

FloatWindow是一个功能强大的悬浮窗库,支持拖动、动画、界面过滤等功能。其核心特点包括:

  • 权限处理:自动处理4.4-7.0系统版本的权限申请
  • 拖动动画:支持流畅的拖动和边缘吸附效果
  • 界面过滤:可设定特定Activity显示或隐藏悬浮窗
  • 百分比定位:支持屏幕宽度和高度的百分比定位

使用FloatWindow库可以大大简化悬浮窗的开发工作。以下是基本的集成步骤:

  1. 在build.gradle中添加依赖:
implementation 'com.github.yhaolpz:FloatWindow:1.0.0'
  1. 初始化并显示悬浮窗:
FloatWindow.with(this)
    .setView(R.layout.floating_window)
    .setWidth(70)
    .setHeight(70)
    .setX(0)
    .setY(100)
    .setFilterActivity(MainActivity.class)
    .build()
    .show();

FloatWindow库的源码地址:https://gitcode.com/gh_mirrors/fl/FloatWindow

04

注意事项

  1. 性能影响:悬浮窗会占用系统资源,建议在低配置设备上谨慎使用。
  2. 隐私保护:避免在悬浮窗中显示敏感信息,特别是在公共场合使用时。
  3. 用户体验:合理设置悬浮窗的位置和大小,避免遮挡重要界面元素。

通过本文的介绍,相信你已经掌握了Android悬浮窗开发的核心技巧。无论是实现简单的悬浮按钮,还是复杂的悬浮窗应用,都可以基于这些知识进行开发。希望这些内容能帮助你提升开发效率,为用户带来更好的使用体验。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号