Android实现全局悬浮框
作者:tracydragonlxy 发布时间:2021-11-22 12:15:40
标签:Android,悬浮框
本文实例为大家分享了Android实现全局悬浮框的具体代码,供大家参考,具体内容如下
效果图:
代码实现:
Androidmanifest.xml添加弹框权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
自定义悬浮窗类FloatWindow.java
public class FloatWindow implements View.OnTouchListener {
private Context mContext;
private WindowManager.LayoutParams mWindowParams;
private WindowManager mWindowManager;
private View mFloatLayout;
private float mInViewX;
private float mInViewY;
private float mDownInScreenX;
private float mDownInScreenY;
private float mInScreenX;
private float mInScreenY;
private TextView infoText;
public FloatWindow(Context context) {
this.mContext = context;
initFloatWindow();
}
private void initFloatWindow() {
LayoutInflater inflater = LayoutInflater.from(mContext);
if(inflater == null)
return;
mFloatLayout = (View) inflater.inflate(R.layout.layout_float, null);
infoText = mFloatLayout.findViewById(R.id.textView);
mFloatLayout.setOnTouchListener(this);
mWindowParams = new WindowManager.LayoutParams();
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= 26) {//8.0新特性
mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else{
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
mWindowParams.format = PixelFormat.RGBA_8888;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowParams.gravity = Gravity.START | Gravity.TOP;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return floatLayoutTouch(motionEvent);
}
private boolean floatLayoutTouch(MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取相对View的坐标,即以此View左上角为原点
mInViewX = motionEvent.getX();
mInViewY = motionEvent.getY();
// 获取相对屏幕的坐标,即以屏幕左上角为原点
mDownInScreenX = motionEvent.getRawX();
mDownInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);
mInScreenX = motionEvent.getRawX();
mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);
break;
case MotionEvent.ACTION_MOVE:
// 更新浮动窗口位置参数
mInScreenX = motionEvent.getRawX();
mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);
mWindowParams.x = (int) (mInScreenX- mInViewX);
mWindowParams.y = (int) (mInScreenY - mInViewY);
// 手指移动的时候更新小悬浮窗的位置
mWindowManager.updateViewLayout(mFloatLayout, mWindowParams);
break;
case MotionEvent.ACTION_UP:
// 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。
if (mDownInScreenX == mInScreenX && mDownInScreenY == mInScreenY){
}
break;
}
return true;
}
public void showFloatWindow(){
if (mFloatLayout.getParent() == null){
DisplayMetrics metrics = new DisplayMetrics();
// 默认固定位置,靠屏幕右边缘的中间
mWindowManager.getDefaultDisplay().getMetrics(metrics);
mWindowParams.x = metrics.widthPixels;
mWindowParams.y = metrics.heightPixels/2 - getSysBarHeight(mContext);
mWindowManager.addView(mFloatLayout, mWindowParams);
}
}
public void updateText(final String s) {
infoText.setText(s);
}
public void hideFloatWindow(){
if (mFloatLayout.getParent() != null)
mWindowManager.removeView(mFloatLayout);
}
public void setFloatLayoutAlpha(boolean alpha){
if (alpha)
mFloatLayout.setAlpha((float) 0.5);
else
mFloatLayout.setAlpha(1);
}
// 获取系统状态栏高度
public static int getSysBarHeight(Context contex) {
Class<?> c;
Object obj;
Field field;
int x;
int sbar = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
sbar = contex.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return sbar;
}
}
自定义悬浮窗界面布局文件layout_float.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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/float_win"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00ffffff"
android:text="hello"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="@id/imageView"
app:layout_constraintRight_toRightOf="@id/imageView"
app:layout_constraintTop_toBottomOf="@id/imageView"/>
</android.support.constraint.ConstraintLayout>
在Activity中使用悬浮窗。
public class MainActivity extends AppCompatActivity {
private Button btnShow;
FloatWindow floatWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 权限判断
if (Build.VERSION.SDK_INT >= 23) {
if(!Settings.canDrawOverlays(getApplicationContext())) {
// 启动Activity让用户授权
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));
startActivityForResult(intent,10);
} else {
// 执行6.0以上绘制代码
initView();
}
} else {
// 执行6.0以下绘制代码
initView();
}
}
@Override
protected void onResume() {
super.onResume();
// 权限判断
if (Build.VERSION.SDK_INT >= 23) {
if(Settings.canDrawOverlays(getApplicationContext())) {
initView();
}
} else {
//执行6.0以下绘制代码
initView();
}
}
private void initView() {
setContentView(R.layout.activity_main);
floatWindow = new FloatWindow(getApplicationContext());
btnShow = findViewById(R.id.btn_show);
btnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (null != floatWindow) {
floatWindow.showFloatWindow();
}
}
});
Button btnrefresh = findViewById(R.id.btn_refresh);
btnrefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int random = (int) (Math.random() * 10);
if (null != floatWindow) {
floatWindow.updateText(String.valueOf(random));
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (null != floatWindow) {
floatWindow.hideFloatWindow();
}
}
}
来源:https://blog.csdn.net/tracydragonlxy/article/details/103513842


猜你喜欢
- 本文实例讲述了C#采用OpenXml实现给word文档添加文字的方法,分享给大家供大家参考。具体方法如下:一般来说,使用OpenXml给wo
- 本文实例为大家分享了C语言实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下程序介绍代码#include<stdafx.h>?
- 一、返回一般数据类型比如要根据 id 属性获得数据库中的某个字段值。mapper 接口:// 根据 id 获得数据库中的 username
- Java 继承与多态的深入理解1、 什么是继承,继承的特点?子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。或子类从
- using System;using System.Collections.Generic;public class Example{ &n
- 源码:[StructLayout(LayoutKind.Explicit)] public struct IP {&nb
- 一、使用swing嵌套浏览器要实现的功能:通过java的swing实现在一个窗体中嵌套一个浏览器,可以在这个浏览器中将另一个项目的内容显示出
- 一、什么是过滤器过滤器是对数据进行过滤,预处理过程,当我们访问网站时,有时候会发布一些敏感信息,发完以后有的会用*替代,还有就是登陆权限控制
- file: BluetoothEventLoop.java GB/GB2/GB3: 1. import android.os.PowerMa
- 本文实例讲述了Spring实战之SpEl语法。分享给大家供大家参考,具体如下:一 Beanpackage org.crazyit.app.d
- 目录 Dubbo是什么?Dubbo能做什么?介绍Api模块实现producer模块实现consumer模块实现 Dubb
- 本教程源码https://github.com/bestaone/HiAuth源码比较全面,教程我就只介绍关键代码了,喜欢的点个star,谢
- 一、前言在软件开发中,经常用到设置这样的功能,如果设置中的功能不多,用 Json、XML 这样的数据结构存储非常的麻烦,一个字段的读写,就要
- 本文实例为大家分享了C#十五子游戏的具体代码,供大家参考,具体内容如下using System;using System.Collectio
- 本文实例讲述了Java包装类原理与用法。分享给大家供大家参考,具体如下:产生:为了提高数据类型的的面向对象性,所以产生了包装类,包装类中有各
- Word中设置水印时,可加载图片设置为水印效果,但通常添加水印效果时,会对所有页面都设置成统一效果,如果需要对每一页或者某个页面设置不同的水
- 鉴于谷歌最新推出的Android Studio备受开发者的推崇,所以也跟着体验一下。一、介绍Android Studio Andr
- 对话框(Dialog)是Android系统在Activity或者其他组件运行过程中提供的一种提示机制。它可以帮助应用完成一些必要的提示功能,
- 教你一步一步用 java 设计生成二维码在物联网的时代,二维码是个很重要的东西了,现在无论什么东西都要搞个二维码标志,唯恐落伍,就差人没有用
- 模式虽然精妙,却难完美,比如观察者模式中观察者生命周期的问题;比如访问者模式中循环依赖的问题等等;其它很多模式也存在这样那样的一些不足之处,