IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【安卓】悬浮球源代码(长按判断、多次点击判断、自动贴边) -> 正文阅读

[移动开发]【安卓】悬浮球源代码(长按判断、多次点击判断、自动贴边)

实现悬浮球需要了解

  • Winodw和WindowManager
  • Serivce

版本:Android10
Android studio版本:2020.3.1
targetVersion :30 (需26+)
开发时gradle版本;com.android.tools.build:gradle:7.0.0
应用权限:ACTION_MANAGE_OVERLAY_PERMISSION


实现的效果:

  • 可短按
  • 可长按(在刚点击的时候,不会触发短按点击事件),可两次长按
  • 10秒钟不点击,变成透明度80%的悬浮球,不会遮挡到悬浮球后方文字

悬浮球预览:(想要无损图片的关注私聊我)
在这里插入图片描述


开始实现

1.使用类型

首先要明确,Activity是无法完成在桌面悬浮的一个悬浮球的,我们必须要用到Service,这里不赘述,Service和Activity很类似,但是前置主要用于一些后台服务,配合WindowManager可以完成悬浮球的效果(应用程序关闭,服务关闭)。

2.权限

至少需要用到弹窗权限,如果悬浮球需要添加其他功能,按需添加权限

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

3.准备图片资源

需要的关注私聊

4.编写代码

1.获取屏幕参数

    public void getSizeOfScreen(){
        WindowManager windowManager=(WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        SCREEN_HEIGHT=windowManager.getDefaultDisplay().getHeight();
        SCREEN_WIDTH=windowManager.getDefaultDisplay().getWidth();
    }

屏幕参数在这里很重要,防止悬浮球遇到显示在屏幕外

2.initWindowManager

    @RequiresApi(api = Build.VERSION_CODES.O)
    @SuppressLint("ClickableViewAccessibility")
    public void initWindowManager() {
        windowManager = (WindowManager) getApplicationContext()
                .getSystemService(Context.WINDOW_SERVICE);
        //这里是获得WindowManager绑定的视图,等下和下面的是呼应的,相当于两者绑定在一块了,绑定了我们才能用Manger来控制悬浮球
        //   floatView = new View(getApplicationContext());

        params = new WindowManager.LayoutParams();
        // 设置Window Type
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }
        // 设置悬浮框不可触摸
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        // 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应
        params.format = PixelFormat.RGBA_8888;

        // 自动设置悬浮框的合适宽高
        setSizeOfBall();
        params.gravity = Gravity.LEFT;
        params.x = 200;
        params.y = 000;
    }

代码中的if-else语句很重要,在网上某些过时的博客中,没有这段代码,会报权限类型错误
注:parm代表的就是悬浮球的所在位置
想控制自己的悬浮球一定要知道安卓手机屏幕的View坐标系
在这里插入图片描述3.代码

public void Drag() {

        // 设置悬浮框的Touch监听
        if (IS_SHOW) {
            floatView.setOnTouchListener(new View.OnTouchListener() {
                //保存悬浮框最后位置的变量
                int lastX, lastY;
                int paramX, paramY;
                int old_dx = 0, old_dy = 0;

                //思路:在只触摸的时候,移动悬浮球会触发ontouch监听器,(假如松开手,悬浮球会自动贴边),假如在触摸且未贴边的情况下,如果悬浮在非边缘部分
                //就可以调用截图功能,开启截图
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            lastX = (int) event.getRawX();
                            lastY = (int) event.getRawY();
                            paramX = params.x;
                            paramY = params.y;
                            isMove=true;//移动的标志
                            setDrawable();
                            downTime=System.currentTimeMillis();
                            Log.i(TAG, "onTouch: ACTION_DOWN");
                            break;
                        case MotionEvent.ACTION_MOVE:
                            int dx = (int) event.getRawX() - lastX;
                            int dy = (int) event.getRawY() - lastY;
                            params.x = paramX + dx;
                            params.y = paramY + dy;
                            //判断是否是长按
                            isLongPress(event,lastX,lastY);
                            windowManager.updateViewLayout(floatView, params);
                            Log.i(TAG, "onTouch:ACTION_MOVE");
                            old_dy = dy;
                            old_dx = dx;
                            IsTransparent=false;
                            handler.removeMessages(flag3);
                            break;
//                            取消点击后,获取当前位置,横向方向变为0,
                        case MotionEvent.ACTION_UP:
                            Log.i(TAG, "onTouch: ACTION_CANCEL" );
                            
                           //这里是简单的自动贴边功能
                            if (params.x>SCREEN_WIDTH/2){
                                params.x=SCREEN_WIDTH;
                                windowManager.updateViewLayout(floatView,params);
                            }
                            else{
                                params.x=0;
                                windowManager.updateViewLayout(floatView,params);
                            }
                            
                            isOnceLongPress=false;
                            isMove=false;
                            isTwiceLongPress=false;
                            Transparent();//设置悬浮球图片为80透明
                            break;
                    }
                    v.performClick();
                    return true;
//                    onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发
//                    假如onTouch方法返回false会接着触发onTouchEvent,反之onTouchEvent方法不会被调用
//                    内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发
//                    顺序为: onTouch—–>onTouchEvent—>onClick
                    //资料地址https://blog.csdn.net/DreamingOfDreams/article/details/83592238
                }
            });
            windowManager.addView(floatView, params);

            Log.i(TAG, "Drag: 悬浮球已经addView");
        }
    }


给悬浮球加了监听器,监听其的点击,并实现跟随点击改变位置
图中用到了Handler,是为了解决一个自定义手势,两次长按事件
这里不详细解释Handler是什么,简而言之说明其功能,就是在代码中可以发送信号,然后Handler 接收到信号后执行相应代码,并且有延迟发送,和取消发送功能。

我在demo中用到了以下功能

  • 延迟发送:可以解决悬浮球在非点击后10秒钟就改变透明度的事件
  • 取消发送:假如10秒内有点击事件,取消发送改变透明度的信号
    注意:延迟发送信号一定会到达的,并且一定会触发相应代码,触发在发送之前取消发送
    handler.sendEmptyMessageDelayed(flag1,1000);
    @SuppressLint("HandlerLeak")
    public void initHandler(){
        handler=new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                switch (msg.what){
                    case flag1:
                        isOnceLongPress=true;
                        handler.removeMessages(flag1);//防止消息溢出导致发生两次该事件
                        Log.d(TAG, "handleMessage: 长按事件1" );
                        break;
                    case flag2:
                        isTwiceLongPress=true;
                        handler.removeMessages(flag2);
                        Log.d(TAG, "handleMessage: 长按事件2" );
                        break;
                    case flag3:
                        IsTransparent=true;
                        handler.removeMessages(flag3);
                        Log.d(TAG, "handleMessage: 透明事件" );
                        floatView.setBackgroundResource(R.drawable.ic_floatball_transparent80);
                        break;
                }
            }
        };
    }

给悬浮球设置图片:如果透明就设置图片,如果没有显示就创建

    public void setDrawable() {
        if (IsTransparent){
            floatView.setBackgroundResource(R.drawable.ic_float_ball);
            return;
        }
        if (!IS_SHOW) {
            floatView = new View(getApplicationContext());
            floatView.setBackgroundResource(R.drawable.ic_float_ball);
//            floatView.setBackgroundColor(Color.TRANSPARENT);
            IS_SHOW = true;
            Log.d(TAG, "setDrawable: 悬浮球图片已加载完成");
        }
    }

需要demo私聊

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-04 11:08:59  更:2022-02-04 11:10:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 13:25:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码