欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现悬浮窗全系统版本

程序员文章站 2023-10-31 08:52:04
悬浮窗是在系统上显示的内容,好像微信视频聊天时的小窗口一样,在退出软件后依然存在的一个窗口,本博客以窗口中放一个button组件为例,简单展示悬浮窗,其中包括了对android 6.0...

悬浮窗是在系统上显示的内容,好像微信视频聊天时的小窗口一样,在退出软件后依然存在的一个窗口,本博客以窗口中放一个button组件为例,简单展示悬浮窗,其中包括了对android 6.0以下、android 6.0到android 8.0、android 8.0以上版本的处理,下面开始介绍实现方法:

1、mainactivity中的代码

public button mfloatingbutton;
 
 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
 
  //初始化view
  initview();
 }
 //初始化view
 private void initview() {
  mfloatingbutton=(button) findviewbyid(r.id.floating_btn);
  mfloatingbutton.setonclicklistener(this);
 }
 
 public void startfloatingbuttonservice(view view) {
  log.e("测试流程", "测试流程");
  if (floatingservice_button.isstarted) {
   log.e("测试流程2", "测试流程2");
   return;
  }
  if (build.version.sdk_int >= build.version_codes.m) {//判断系统版本
   if (!settings.candrawoverlays(this)) {
    toast.maketext(this, "当前无权限,请授权", toast.length_short);
    log.e("测试流程3", "测试流程3");
    startactivityforresult(new intent(settings.action_manage_overlay_permission, uri.parse("package:" + getpackagename())), 0);
   } else {
    log.e("测试流程4", "测试流程4");
    startservice(new intent(mainactivity.this, floatingservice_button.class));
   }
  } else {
   startservice(new intent(mainactivity.this, floatingservice_button.class));
  }
 
 }
 
 @override
 protected void onactivityresult(int requestcode, int resultcode, intent data) {
  if (requestcode == 0) {
   if (!settings.candrawoverlays(this)) {
    log.e("测试流程5", "测试流程5");
    toast.maketext(this, "授权失败", toast.length_short).show();
   } else {
    log.e("测试流程6", "测试流程6");
    toast.maketext(this, "授权成功", toast.length_short).show();
    startservice(new intent(mainactivity.this, floatingservice_button.class));
   }
  }
 }
 
 @override
 public void onclick(view v) {
  switch (v.getid()){
   case r.id.floating_btn :
    startfloatingbuttonservice(v);
    break;
  }
 }

思路简单解释:点击弹出悬浮窗按钮时,获取版本并判断“build.version.sdk_int >= build.version_codes.m”如果系统版本在6.0以下这不需要请求权限,如果系统版本在6.0以上需要进行权限检测以及请求,获取权限后,弹出悬浮框

2、activity_main.xml代码

<?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="com.example.jack_lin.suspendwindow.mainactivity">
 
 <button
  android:id="@+id/floating_btn"
  style="@style/floatingbtn"
  android:text="@string/floating_btn" />
 
 
</linearlayout>

简单解释:xml中没什么特别东西,线性布局中放一个按钮

3、floatingservice_button的代码

public static boolean isstarted = false;
 
 private windowmanager windowmanager;
 private windowmanager.layoutparams layoutparams;
 
 private button button;
 
 @override
 public void oncreate() {
  super.oncreate();
  log.e("进入服务1", "进入服务1");
  isstarted = true;
  windowmanager = (windowmanager) getsystemservice(window_service);
  layoutparams = new windowmanager.layoutparams();
  if (build.version.sdk_int >= build.version_codes.o) {
   layoutparams.type = windowmanager.layoutparams.type_application_overlay;
  } else {
   layoutparams.type = windowmanager.layoutparams.type_phone;
  }
  layoutparams.format = pixelformat.rgba_8888;
  layoutparams.gravity = gravity.left | gravity.top;
  layoutparams.flags = windowmanager.layoutparams.flag_not_touch_modal | windowmanager.layoutparams.flag_not_focusable;
  layoutparams.width = 500;
  layoutparams.height = 100;
  layoutparams.x = 300;
  layoutparams.y = 300;
 }
 
 @nullable
 @override
 public ibinder onbind(intent intent) {
  log.e("进入服务2", "进入服务2");
 
  return null;
 }
 
 @override
 public int onstartcommand(intent intent, int flags, int startid) {
  log.e("进入服务3", "进入服务3");
  showfloatingwindow();
  return super.onstartcommand(intent, flags, startid);
 }
 
 private void showfloatingwindow() {
  if (build.version.sdk_int >= build.version_codes.m) {//判断系统版本
   if (settings.candrawoverlays(this)) {
    button = new button(getapplicationcontext());
    button.settext("我是个button窗口");
    button.setbackgroundcolor(color.blue);
    windowmanager.addview(button, layoutparams);
 
    button.setontouchlistener(new floatingontouchlistener());
   }
  } else {
   button = new button(getapplicationcontext());
   button.settext("我是个button窗口");
   button.setbackgroundcolor(color.blue);
   windowmanager.addview(button, layoutparams);
 
   button.setontouchlistener(new floatingontouchlistener());
  }
 }
 
 private class floatingontouchlistener implements view.ontouchlistener {
  private int x;
  private int y;
 
  @override
  public boolean ontouch(view view, motionevent event) {
   switch (event.getaction()) {
    case motionevent.action_down:
     x = (int) event.getrawx();
     y = (int) event.getrawy();
     break;
    case motionevent.action_move:
     int nowx = (int) event.getrawx();
     int nowy = (int) event.getrawy();
     int movedx = nowx - x;
     int movedy = nowy - y;
     x = nowx;
     y = nowy;
     layoutparams.x = layoutparams.x + movedx;
     layoutparams.y = layoutparams.y + movedy;
     windowmanager.updateviewlayout(view, layoutparams);
     break;
    default:
     break;
   }
   return false;
  }
 }

思路简单解释:首先获取windowmanager服务,然后定义并设置在window上显示的layoutparams(此处需注意android 8.0以上版本中layoutparam里的type变量变为type_application_overlay与android 8.0以下版本layoutparam里的type变量type_phone不一样,需要通过判断系统版本进行区分),然后定义并设置在layoutparams上面显示的button按钮以及监听事件(此处的监听事件主要是悬浮窗口拖动的监听)最后将设置好的button与layoutparams添加入window中

4、androidmanifest.xml中权限添加

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

5、效果图

Android实现悬浮窗全系统版本

源码下载地址:android悬浮窗 源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。