android studio悬浮窗

Float Window

1.权限与开启服务
权限

<!--2.悬浮窗警报开启-->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

注册服务

<service android:name=".FloatingWindow"/><!--2.这里是注册服务-->

开启服务(这里是开启服务可以后台,而绑定服务可以传值)

startService(new Intent(this, FloatingWindow.class));//1.开启服务

2.服务类
继承与重写,服务作用:可以在后台运行

extends Service
//重写onBind,必须的
onBind
//onCreate,自己创建
onCreate

创建,LinearLayout,Button,WindowManager
LinearLayout用LinearLayout.LayoutParams设置参数
Button用ViewGroup.LayoutParams设置参数
WindowManager用WindowManager.LayoutParams设置参数
button加LinearLayout里,LineaLayout加到WindowManager里。
3.设置移动监听
touch监听:触碰是为了得到此位置
移动则可以得到移动后的位置,
两者结合便可以得到我们想要的距离
再在WindowManager更新得到我们想要的距离
4.stop
WindowManager移除LinearLayout,再停止服务
5.代码

package com.example.examplefloatwindows;

import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

public class FloatingWindow extends Service {
    private WindowManager wm;
    private LinearLayout ll;
    private String TAG = FloatingWindow.class.getName();

    private Button stop;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        wm = (WindowManager) getSystemService(WINDOW_SERVICE);//3.得到系统服务
        ll = new LinearLayout(this);//在this这里创建LinearLayout
        LinearLayout.LayoutParams LLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);//得到LL的layoutParams实例,设置布局高宽
        ll.setBackgroundColor(Color.argb(66, 255, 0, 0));//透明度,红色,绿色,蓝色
        ll.setLayoutParams(LLayoutParams);//设置布局参数
        final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(400, 150, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);//WindowManager参数实例化
        parameters.x = 0;parameters.y = 0;//位置
        parameters.gravity = Gravity.CENTER | Gravity.CENTER;//重心居中
        /**
         * 按钮
         */
        stop=new Button(this);
        ViewGroup.LayoutParams btnParamters=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        stop.setText("stop");
        stop.setLayoutParams(btnParamters);
        ll.addView(stop);

        wm.addView(ll, parameters);//加入View,参数

        ll.setOnTouchListener(new View.OnTouchListener() {
            private WindowManager.LayoutParams updatedParameters = parameters;
            int x, y;
            float touchedX, touchedY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {//布局,点击之后的位置,级短时间内就更新
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        x = updatedParameters.x;y = updatedParameters.y;//更新的x,y(其实他就是WindowManager的位置),此时都为0
                        touchedX = event.getRawX();touchedY = event.getRawY();//这里表示得到原来的x,y
                        Log.d(TAG, "\n" + x + "\n" + y + "\n" + touchedX + "\n" + touchedY);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        updatedParameters.x = (int) (x + (event.getRawX() - touchedX));updatedParameters.y = (int) (y + (event.getRawY() - touchedY));//getRawY表示移动后现在的距离左侧位置长度,
                        wm.updateViewLayout(ll, updatedParameters);//更新位置
                        Log.d(TAG, "\n" + x + "\n" + y + "\n" + touchedX + "\n" + touchedY);
                }
                return false;
            }
        });

        stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                wm.removeView(ll);//移除布局
                stopSelf();//移除service
            }
        });


    }
}

蹦掉怎么办

修改后代码
MainActivity.class

package com.example.examplefloatwindows;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mBtFloatWindows;

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

    private void initView() {
        mBtFloatWindows = (Button) findViewById(R.id.bt_floatWindows);

        mBtFloatWindows.setOnClickListener(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_floatWindows:
                //如果是已经悬浮状态,就跳出去,都不执行
                if (FloatingWindow.isStarted) {
                    return;
                }
                //如果不可以叠加型绘制
                if (!Settings.canDrawOverlays(this)) {
                    Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT);//显示无权限信息
                    startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 0);//跳转到手机权限设置那里
                } else {//可以叠加绘制
                    startService(new Intent(MainActivity.this, FloatingWindow.class));
                }
                startService(new Intent(this, FloatingWindow.class));//1.开启服务
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d("onActivityResult", "我是这个时候开始的");
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (!Settings.canDrawOverlays(this)) {
                    Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
                    startService(new Intent(MainActivity.this, FloatingWindow.class));
                }
            } else {
                Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
                startService(new Intent(MainActivity.this, FloatingWindow.class));
            }
        }
    }
}

FloatingWindow.java
package com.example.examplefloatwindows;

import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

public class FloatingWindow extends Service {
private WindowManager wm;
private LinearLayout ll;
private String TAG = FloatingWindow.class.getName();

public static boolean isStarted = false;//默认为不显示

private Button stop;
private int typeApplicationOverlay;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();
    isStarted=true;
    wm = (WindowManager) getSystemService(WINDOW_SERVICE);//3.得到系统服务
    ll = new LinearLayout(this);//在this这里创建LinearLayout
    LinearLayout.LayoutParams LLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);//得到LL的layoutParams实例,设置布局高宽
    ll.setBackgroundColor(Color.argb(66, 255, 0, 0));//透明度,红色,绿色,蓝色
    ll.setLayoutParams(LLayoutParams);//设置布局参数
    // 设置窗体显示类型
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        typeApplicationOverlay = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    } else {
        typeApplicationOverlay = WindowManager.LayoutParams.TYPE_PHONE;
    }

    final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(400, 150, typeApplicationOverlay, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);//WindowManager参数实例化
    parameters.x = 0;parameters.y = 0;//位置
    parameters.gravity = Gravity.CENTER | Gravity.CENTER;//重心居中
    /**
     * 按钮
     */
    stop=new Button(this);
    ViewGroup.LayoutParams btnParamters=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
    stop.setText("stop");
    stop.setLayoutParams(btnParamters);
    ll.addView(stop);

    wm.addView(ll, parameters);//加入View,参数

    ll.setOnTouchListener(new View.OnTouchListener() {
        private WindowManager.LayoutParams updatedParameters = parameters;
        int x, y;
        float touchedX, touchedY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {//布局,点击之后的位置,级短时间内就更新
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    x = updatedParameters.x;y = updatedParameters.y;//更新的x,y(其实他就是WindowManager的位置),此时都为0
                    touchedX = event.getRawX();touchedY = event.getRawY();//这里表示得到原来的x,y
                    Log.d(TAG, "\n" + x + "\n" + y + "\n" + touchedX + "\n" + touchedY);
                    break;
                case MotionEvent.ACTION_MOVE:
                    updatedParameters.x = (int) (x + (event.getRawX() - touchedX));updatedParameters.y = (int) (y + (event.getRawY() - touchedY));//getRawY表示移动后现在的距离左侧位置长度,
                    wm.updateViewLayout(ll, updatedParameters);//更新位置
                    Log.d(TAG, "\n" + x + "\n" + y + "\n" + touchedX + "\n" + touchedY);
            }
            return false;
        }
    });

    stop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            isStarted=false;
            wm.removeView(ll);//移除布局
            stopSelf();//移除service
        }
    });


}

}

添加了什么:
TYPE要修改,因为有些只能支持TYPE_APPLICATION_OVERLAY,不支持TYPE_PHONE

// 设置窗体显示类型
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            typeApplicationOverlay = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            typeApplicationOverlay = WindowManager.LayoutParams.TYPE_PHONE;
        }
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值