Android实现全局悬浮框
作者:tracydragonlxy 时间:2021-11-22 12:15:40
本文实例为大家分享了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
标签:Android,悬浮框
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
SpringBoot Test类注入失败的解决
2023-05-20 13:59:40
![](https://img.aspxhome.com/file/2023/4/95954_0s.jpg)
C#检测是否有危险字符的SQL字符串过滤方法
2023-10-11 12:48:48
C# 显示、隐藏窗口对应的任务栏
2023-06-13 03:57:32
![](https://img.aspxhome.com/file/2023/3/87053_0s.png)
springboot结合maven配置不同环境的profile方式
2022-05-28 12:00:16
![](https://img.aspxhome.com/file/2023/6/63416_0s.png)
Eclipse插件大全 挑选最牛的TOP30(全)
2023-06-29 09:34:50
![](https://img.aspxhome.com/file/2023/4/87354_0s.png)
BeanDefinitionRegistryPostProcessor如何动态注册Bean到Spring
2023-11-24 12:56:16
![](https://img.aspxhome.com/file/2023/1/59941_0s.jpg)
Java解决约瑟夫问题代码实例
2023-09-20 19:17:02
Android GestureDetector手势滑动使用实例讲解
2022-01-18 01:34:12
![](https://img.aspxhome.com/file/2023/4/88704_0s.jpg)
详解Spring中bean的几种注入方式
2023-02-12 20:25:07
mybatis关系映射之一对多和多对一
2021-08-01 21:14:26
![](https://img.aspxhome.com/file/2023/3/67973_0s.png)
浅谈JAVA 内存流的实现
2021-06-28 05:43:59
![](https://img.aspxhome.com/file/2023/5/86815_0s.jpg)
C#集合之列表的用法
2021-12-27 19:46:43
Java 输入流中的read(byte[] b)方法详解
2022-08-13 18:58:12
![](https://img.aspxhome.com/file/2023/8/101948_0s.jpg)
java语言自行实现ULID过程底层原理详解
2023-04-13 22:38:50
![](https://img.aspxhome.com/file/2023/7/69097_0s.png)
Java使用备忘录模式实现过关类游戏功能详解
2022-11-30 08:52:51
![](https://img.aspxhome.com/file/2023/2/60782_0s.png)
Java如何利用状态模式(state pattern)替代if else
2021-08-15 09:31:08
![](https://img.aspxhome.com/file/2023/7/87207_0s.jpg)
java多线程Thread的实现方法代码详解
2022-01-03 01:02:28
struts2的国际化实现网站整体中英文切换实例代码
2023-08-31 02:37:40
![](https://img.aspxhome.com/file/2023/2/70982_0s.png)
SpringCache框架加载/拦截原理详解
2023-04-11 10:31:46
web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程
2023-11-24 07:40:52
![](https://img.aspxhome.com/file/2023/9/59929_0s.jpg)