android实现全局悬浮球

android实现悬浮球功能:

设置悬浮球View操作代码:

package lwnewoa.zjsos.com.floadballdemo;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Build;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

/**
 * Author:Stephen
 * Blog: https://me.csdn.net/jifenglie
 * Date:2020/3/16
 * Description:
 */

public class FloatBallView {


    private Context context;

    private int height = 0;

    private int width = 0;

    public static FloatBallView floatView2;


    public static FloatBallView getInstance(Context context) {
        if (floatView2 == null) {
            floatView2 = new FloatBallView(context);
        }
        return floatView2;
    }

    public FloatBallView(Context c) {

        this.context = c;

    }

    private WindowManager wm;

    private View view;// 浮动按钮

    WindowManager.LayoutParams params;

    /**
     * 添加悬浮View
     *
     * @param
     */

    public void createFloatView() {

        if (view == null) {
            view = LayoutInflater.from(context).inflate(R.layout.home_floatview, null);
        }


        wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        height = wm.getDefaultDisplay().getHeight();
        width = wm.getDefaultDisplay().getWidth();

        params = new WindowManager.LayoutParams();
        params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;// 所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        params.format = PixelFormat.TRANSLUCENT;// 不设置这个弹出框的透明遮罩显示为黑色
        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.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.gravity = Gravity.TOP | Gravity.LEFT;
        int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
        int screenHeight = context.getResources().getDisplayMetrics().heightPixels;
        params.y = screenHeight - height / 3;//设置距离底部高度为屏幕三分之一
        params.x = screenWidth;
        view.setBackgroundColor(Color.TRANSPARENT);
        view.setVisibility(View.VISIBLE);
        view.setOnTouchListener(new View.OnTouchListener() {
            // 触屏监听
            float lastX, lastY;
            int oldOffsetX, oldOffsetY;
            int tag = 0;// 悬浮球 所需成员变量

            @Override

            public boolean onTouch(View v, MotionEvent event) {
                final int action = event.getAction();
                float x = event.getX();
                float y = event.getY();
                if (tag == 0) {
                    oldOffsetX = params.x; // 偏移量
                    oldOffsetY = params.y; // 偏移量
                }

                if (action == MotionEvent.ACTION_DOWN) {
                    lastX = x;
                    lastY = y;
                } else if (action == MotionEvent.ACTION_MOVE) {
                    params.x += (int) (x - lastX) / 3; // 减小偏移量,防止过度抖动
                    params.y += (int) (y - lastY) / 3; // 减小偏移量,防止过度抖动
                    tag = 1;
                    wm.updateViewLayout(view, params);
                } else if (action == MotionEvent.ACTION_UP) {
                    int newOffsetX = params.x;
                    int newOffsetY = params.y;
// 只要按钮一动位置不是很大,就认为是点击事件
                    if (Math.abs(oldOffsetX - newOffsetX) <= 20
                            && Math.abs(oldOffsetY - newOffsetY) <= 20) {
                        if (l != null) {
                            l.onClick(view);
                        }
                    } else {
                        if (params.x < width / 2) {
                            params.x = 0;
                        } else {
                            params.x = width;
                        }
                        wm.updateViewLayout(view, params);
                        tag = 0;
                    }
                }
                return true;
            }
        });
        try {
            wm.addView(view, params);
        } catch (Exception e) {

        }

        /*floatView2.onFloatViewClick(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//这边是点击悬浮按钮的响应事件
                Toast.makeText(context, "点击了悬浮球", Toast.LENGTH_LONG);
            }
        });*/
    }

    /**
     * 点击浮动按钮触发事件,需要override该方法
     */

    private View.OnClickListener l;

    public void onFloatViewClick(View.OnClickListener l) {
        this.l = l;
    }

    /**
     * 将悬浮View从WindowManager中移除,需要与createFloatView()成对出现
     */

    public void removeFloatView() {
        if (wm != null && view != null) {
            wm.removeViewImmediate(view);
// wm.removeView(view);//不要调用这个,WindowLeaked
            view = null;
            wm = null;
        }
    }

    /**
     * 隐藏悬浮View
     */

    public void hideFloatView() {
        if (wm != null && view != null && view.isShown()) {
            view.setVisibility(View.GONE);
        }
    }

    /**
     * 显示悬浮View
     */

    public void showFloatView() {
        if (wm != null && view != null && !view.isShown()) {
            view.setVisibility(View.VISIBLE);
        }
    }

    public void updateViewLayout() {
        if (wm != null) {
            int screenWidth = (int) 480;
            int screenHeight = (int) 720;
            if (screenWidth == 0) {
                screenWidth = context.getResources().getDisplayMetrics().widthPixels;
            }

            if (screenHeight == 0) {
                screenHeight = context.getResources().getDisplayMetrics().heightPixels;
                params.y = screenHeight - height / 3;//设置距离底部高度为屏幕三分之一
            } else {
                params.y = screenHeight;
            }
            params.x = screenWidth;
            wm.updateViewLayout(view, params);
        }

    }

}

home_floatview.xml : 

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <de.hdodenhof.circleimageview.CircleImageView
        android:layout_width="96dp"
        android:layout_height="96dp"
        android:src="@drawable/ic_home_zfxzs" />

</android.support.constraint.ConstraintLayout>

项目首页使用:

package lwnewoa.zjsos.com.floadballdemo;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Button button1 = findViewById(R.id.button1);
        Button button2 = findViewById(R.id.button2);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //检查是否已经授予权限
                    if (!Settings.canDrawOverlays(MainActivity.this)) {
                        //若未授权则请求权限
                        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                        intent.setData(Uri.parse("package:" + getPackageName()));
                        startActivityForResult(intent, 0);
                    }
                }
            }
        });

        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FloatBallView.getInstance(MainActivity.this).createFloatView();

            }
        });

//这边是点击悬浮按钮的响应事件

        FloatBallView.getInstance(MainActivity.this).onFloatViewClick(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "点击了悬浮球", Toast.LENGTH_LONG).show();
            }
        });


    }
}

 activity_main :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="lwnewoa.zjsos.com.floadballdemo.MainActivity">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="50dp"
        android:text="获取悬浮球权限" />


    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="10dp"
        android:text="打开悬浮球" />

</LinearLayout>

权限:

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

第三方 圆形图片

implementation 'de.hdodenhof:circleimageview:2.1.0'

项目地址:FloadBallDemo.zip-Android代码类资源-CSDN下载

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值