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

标签:Android,悬浮框
0
投稿

猜你喜欢

  • SpringBoot Test类注入失败的解决

    2023-05-20 13:59:40
  • C#检测是否有危险字符的SQL字符串过滤方法

    2023-10-11 12:48:48
  • C# 显示、隐藏窗口对应的任务栏

    2023-06-13 03:57:32
  • springboot结合maven配置不同环境的profile方式

    2022-05-28 12:00:16
  • Eclipse插件大全 挑选最牛的TOP30(全)

    2023-06-29 09:34:50
  • BeanDefinitionRegistryPostProcessor如何动态注册Bean到Spring

    2023-11-24 12:56:16
  • Java解决约瑟夫问题代码实例

    2023-09-20 19:17:02
  • Android GestureDetector手势滑动使用实例讲解

    2022-01-18 01:34:12
  • 详解Spring中bean的几种注入方式

    2023-02-12 20:25:07
  • mybatis关系映射之一对多和多对一

    2021-08-01 21:14:26
  • 浅谈JAVA 内存流的实现

    2021-06-28 05:43:59
  • C#集合之列表的用法

    2021-12-27 19:46:43
  • Java 输入流中的read(byte[] b)方法详解

    2022-08-13 18:58:12
  • java语言自行实现ULID过程底层原理详解

    2023-04-13 22:38:50
  • Java使用备忘录模式实现过关类游戏功能详解

    2022-11-30 08:52:51
  • Java如何利用状态模式(state pattern)替代if else

    2021-08-15 09:31:08
  • java多线程Thread的实现方法代码详解

    2022-01-03 01:02:28
  • struts2的国际化实现网站整体中英文切换实例代码

    2023-08-31 02:37:40
  • SpringCache框架加载/拦截原理详解

    2023-04-11 10:31:46
  • web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程

    2023-11-24 07:40:52
  • asp之家 软件编程 m.aspxhome.com