当前位置: 代码网 > it编程>App开发>Android > Android Studio实现自定义全局悬浮按钮的示例代码

Android Studio实现自定义全局悬浮按钮的示例代码

2025年04月24日 Android 我要评论
一、基础实现方案1. 使用 windowmanager 实现全局悬浮窗这是最灵活的实现方式,可以在任何界面显示悬浮按钮:public class floatingbuttonservice exten

一、基础实现方案

1. 使用 windowmanager 实现全局悬浮窗

这是最灵活的实现方式,可以在任何界面显示悬浮按钮:

public class floatingbuttonservice extends service {
    private windowmanager windowmanager;
    private view floatingbutton;

    @override
    public ibinder onbind(intent intent) {
        return null;
    }

    @override
    public void oncreate() {
        super.oncreate();
        
        // 创建悬浮按钮视图
        floatingbutton = layoutinflater.from(this).inflate(r.layout.floating_button, null);
        
        // 设置按钮点击事件
        floatingbutton.findviewbyid(r.id.float_button).setonclicklistener(v -> {
            // 处理点击事件
            toast.maketext(this, "悬浮按钮被点击", toast.length_short).show();
        });

        // 设置窗口参数
        windowmanager.layoutparams params = new windowmanager.layoutparams(
            windowmanager.layoutparams.wrap_content,
            windowmanager.layoutparams.wrap_content,
            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并添加视图
        windowmanager = (windowmanager) getsystemservice(window_service);
        windowmanager.addview(floatingbutton, params);
        
        // 添加拖拽功能
        adddragfeature();
    }

    private void adddragfeature() {
        floatingbutton.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(floatingbutton, params);
                        return true;
                }
                return false;
            }
        });
    }

    @override
    public void ondestroy() {
        super.ondestroy();
        if (floatingbutton != null) {
            windowmanager.removeview(floatingbutton);
        }
    }
}

2. 布局文件 (res/layout/floating_button.xml)

<?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">

    <imagebutton
        android:id="@+id/float_button"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:background="@drawable/circle_background"
        android:src="@drawable/ic_float_button"
        android:elevation="8dp"
        android:layout_margin="16dp" />

</framelayout>

3. 圆形背景 (res/drawable/circle_background.xml)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/colorprimary" />
</shape>

4. 启动服务

// 在需要显示悬浮按钮的地方启动服务
startservice(new intent(context, floatingbuttonservice.class));

// 停止服务
stopservice(new intent(context, floatingbuttonservice.class));

二、权限处理

1. androidmanifest.xml 中添加权限

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

2. 检查并请求权限

// 检查悬浮窗权限
if (build.version.sdk_int >= build.version_codes.m) {
    if (!settings.candrawoverlays(this)) {
        intent intent = new intent(settings.action_manage_overlay_permission,
                uri.parse("package:" + getpackagename()));
        startactivityforresult(intent, overlay_permission_req);
    } else {
        // 已经有权限,启动服务
        startservice(new intent(this, floatingbuttonservice.class));
    }
} else {
    // 6.0以下直接启动
    startservice(new intent(this, floatingbuttonservice.class));
}

三、高级功能扩展

1. 添加动画效果

// 在按钮点击时添加动画
floatingbutton.setonclicklistener(v -> {
    // 缩放动画
    objectanimator scalex = objectanimator.offloat(v, "scalex", 1f, 0.8f, 1f);
    objectanimator scaley = objectanimator.offloat(v, "scaley", 1f, 0.8f, 1f);
    
    animatorset animatorset = new animatorset();
    animatorset.playtogether(scalex, scaley);
    animatorset.setduration(200);
    animatorset.start();
    
    // 执行点击操作
    performbuttonaction();
});

2. 自动吸附边缘

private void autoattachtoedge() {
    int screenwidth = getresources().getdisplaymetrics().widthpixels;
    int buttonwidth = floatingbutton.getwidth();
    
    if (params.x < screenwidth / 2 - buttonwidth / 2) {
        // 吸附到左边
        params.x = 0;
    } else {
        // 吸附到右边
        params.x = screenwidth - buttonwidth;
    }
    
    windowmanager.updateviewlayout(floatingbutton, params);
}

3. 显示/隐藏动画

public void hidebutton() {
    floatingbutton.animate()
        .translationy(floatingbutton.getheight())
        .setduration(300)
        .start();
}

public void showbutton() {
    floatingbutton.animate()
        .translationy(0)
        .setduration(300)
        .start();
}

四、优化建议

  1. 性能优化

    • 使用轻量级的视图层级
    • 避免频繁调用 updateviewlayout
    • 使用硬件加速
  2. 内存管理

    • 在不需要时及时移除悬浮窗
    • 在低内存时自动隐藏
  3. 用户体验

    • 添加适当的触摸反馈
    • 考虑屏幕旋转时的位置调整
    • 提供设置选项让用户自定义位置和行为
  4. 兼容性处理

    • 处理不同 android 版本的权限差异
    • 适配各种屏幕尺寸和密度
    • 考虑全面屏和刘海屏的适配

五、替代方案

1. 使用 coordinatorlayout + floatingactionbutton

如果只需要在应用内显示悬浮按钮,可以使用 material design 组件:

<androidx.coordinatorlayout.widget.coordinatorlayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 其他内容 -->

    <com.google.android.material.floatingactionbutton.floatingactionbutton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:src="@drawable/ic_add" />

</androidx.coordinatorlayout.widget.coordinatorlayout>

2. 使用第三方库

一些流行的悬浮按钮库:

六、常见问题解决

  1. 权限问题

    • 确保已正确请求 system_alert_window 权限
    • 在 android 6.0+ 上需要动态请求权限
    • 某些厂商 rom 可能需要额外的白名单设置
  2. 位置不正确

    • 检查 windowmanager.layoutparams 的 gravity 设置
    • 考虑状态栏和导航栏的高度
    • 在屏幕旋转时更新位置
  3. 点击穿透

    • 设置 flag_not_focusable 可能导致点击事件穿透
    • 可以通过在 ontouch 中返回 true 来拦截事件
  4. 内存泄漏

    • 确保在服务销毁时移除视图
    • 避免在视图中持有 activity 引用

以上就是android studio实现自定义全局悬浮按钮的示例代码的详细内容,更多关于android studio悬浮按钮的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com