当前位置: 首页 > news >正文

Android 控件 - 悬浮常驻文本遮挡处理策略(问题复现、处理策略、FLAG_NOT_FOCUSABLE 的效果体现)

一、悬浮常驻文本遮挡问题复现

1、Service
  • FloatingTextViewService.java
publicclassFloatingTextViewServiceextendsService{privateTextViewtvFloating;privateWindowManagerwindowManager;@Nullable@OverridepublicIBinderonBind(Intentintent){returnnull;}@OverridepublicvoidonCreate(){super.onCreate();windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);// 创建布局参数WindowManager.LayoutParamsparams=newWindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,Build.VERSION.SDK_INT>=Build.VERSION_CODES.O?WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);// 设置位置为左下角params.gravity=Gravity.BOTTOM|Gravity.START;params.x=0;params.y=0;LayoutInflaterinflater=LayoutInflater.from(this);tvFloating=(TextView)inflater.inflate(R.layout.floating_text_view,null);tvFloating.setText("test content");// 添加到窗口windowManager.addView(tvFloating,params);}@OverridepublicvoidonDestroy(){super.onDestroy();if(tvFloating!=null){windowManager.removeView(tvFloating);}}}
  • floating_text_view.xml
<?xml version="1.0" encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/tv_floating"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="12dp"android:textSize="14sp"/>
2、Manifest
  • AndroidManifest.xml
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW"/><application>...<serviceandroid:name=".service.FloatingTextViewService"android:enabled="true"android:exported="false"/></application>
3、Activity Layout
  • activity_floating_text_view_service.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FloatingTextViewServiceActivity"><Buttonandroid:id="@+id/btn_test"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="test"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
  • FloatingTextViewServiceActivity.java
publicclassFloatingTextViewServiceActivityextendsAppCompatActivity{privatestaticfinalStringTAG=FloatingTextViewServiceActivity.class.getSimpleName();privateActivityResultLauncher<Intent>overlayPermissionLauncher;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_floating_text_view_service);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});test();}privatevoidtest(){overlayPermissionLauncher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(checkOverlayPermission()){createFloatingTextView();}else{Toast.makeText(this,"请先开启浮窗权限",Toast.LENGTH_SHORT).show();}});if(checkOverlayPermission()){createFloatingTextView();}else{requestOverlayPermission();}ButtonbtnTest=findViewById(R.id.btn_test);btnTest.setOnClickListener(v->{Log.i(TAG,"btnTest click");});}privatebooleancheckOverlayPermission(){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){if(Settings.canDrawOverlays(this)){returntrue;}else{returnfalse;}}returntrue;}privatevoidrequestOverlayPermission(){Intentintent=newIntent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:"+getPackageName()));overlayPermissionLauncher.launch(intent);}privatevoidcreateFloatingTextView(){Intentintent=newIntent(this,FloatingTextViewService.class);startService(intent);}}
5、Test
  • 页面中的按钮,因为悬浮常驻文本的遮挡,所以很难点击到

二、悬浮常驻文本遮挡处理策略

  1. 设置FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE标志,这是创建不可交互悬浮窗的关键,即窗口无法获得焦点,也无法接受触摸事件
WindowManager.LayoutParamsparams=newWindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,Build.VERSION.SDK_INT>=Build.VERSION_CODES.O?WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,// 使触摸事件穿透PixelFormat.TRANSLUCENT);
  1. 或者,单独设置FLAG_NOT_FOCUSABLE标志
WindowManager.LayoutParamsparams=newWindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,Build.VERSION.SDK_INT>=Build.VERSION_CODES.O?WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,// 使触摸事件穿透PixelFormat.TRANSLUCENT);
标志说明
FLAG_NOT_FOCUSABLE窗口能否获得焦点,设置后,窗口无法获取键盘焦点
FLAG_NOT_TOUCHABLE窗口是否接受触摸事件,设置后,触摸事件可以穿透传递给后面的窗口

三、FLAG_NOT_FOCUSABLE的效果体现

1、Service
  • FloatingEditTextService.java
publicclassFloatingEditTextServiceextendsService{privateLinearLayoutllFloating;privateWindowManagerwindowManager;@Nullable@OverridepublicIBinderonBind(Intentintent){returnnull;}@OverridepublicvoidonCreate(){super.onCreate();windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);// 创建布局参数WindowManager.LayoutParamsparams=newWindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,Build.VERSION.SDK_INT>=Build.VERSION_CODES.O?WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);// 设置位置为左下角params.gravity=Gravity.BOTTOM|Gravity.START;params.x=0;params.y=0;LayoutInflaterinflater=LayoutInflater.from(this);llFloating=(LinearLayout)inflater.inflate(R.layout.floating_edit_text,null);// 添加到窗口windowManager.addView(llFloating,params);}@OverridepublicvoidonDestroy(){super.onDestroy();if(llFloating!=null){windowManager.removeView(llFloating);}}}
  • floating_edit_text.xml
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#22FF0000"android:orientation="vertical"android:padding="20dp"><EditTextandroid:id="@+id/et_test"android:layout_width="200dp"android:layout_height="wrap_content"/></LinearLayout>
2、Manifest
  • AndroidManifest.xml
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW"/><application>...<serviceandroid:name=".service.FloatingEditTextService"android:enabled="true"android:exported="false"/></application>
3、Activity Layout
  • activity_floating_edit_text_service.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FloatingEditTextServiceActivity"></androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
  • FloatingEditTextServiceActivity.java
publicclassFloatingEditTextServiceActivityextendsAppCompatActivity{privateActivityResultLauncher<Intent>overlayPermissionLauncher;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_floating_edit_text_service);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});test();}privatevoidtest(){overlayPermissionLauncher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(checkOverlayPermission()){createFloatingTextView();}else{Toast.makeText(this,"请先开启浮窗权限",Toast.LENGTH_SHORT).show();}});if(checkOverlayPermission()){createFloatingTextView();}else{requestOverlayPermission();}}privatebooleancheckOverlayPermission(){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){if(Settings.canDrawOverlays(this)){returntrue;}else{returnfalse;}}returntrue;}privatevoidrequestOverlayPermission(){Intentintent=newIntent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:"+getPackageName()));overlayPermissionLauncher.launch(intent);}privatevoidcreateFloatingTextView(){Intentintent=newIntent(this,FloatingEditTextService.class);startService(intent);}}
5、Test
  1. 设置FLAG_NOT_FOCUSABLE标志,无法使用 EditText 输入内容

  2. 设置参数为 0,即可使用 EditText 输入内容

  • 注:设置FLAG_NOT_FOCUSABLEFLAG_NOT_TOUCHABLEFLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE标志,都无法使用 EditText 输入内容
http://www.jsqmd.com/news/434283/

相关文章:

  • 《缺失的数字》——诗解力扣题目
  • 应届生求职机构哪家更好?96%offer交付+名企内推(26年榜单) - 品牌排行榜
  • 我用python-int复刻“银行家算法”(四舍六入五成双)
  • 可以提供市场调查服务的网站有哪些:2026实力榜单(附评测) - 品牌排行榜
  • 2026年肌肉拉伤吃什么品牌的保健品有助于恢复(选购防坑指南) - 品牌排行榜
  • Vue - Vue3 与 Vue2 自定义指令(自定义指令实现、自定义指令钩子函数)
  • 树莓派 (ARM) 运行 redroid Android Docker
  • 2026年3月双流灭跳蚤公司推荐,精准检测与防治效果深度解析 - 品牌鉴赏师
  • 2026年3月天然苏打水品牌推荐,实力品牌深度解析选购无忧之选 - 品牌鉴赏师
  • Pandas DataFrame API:设计哲学、性能调优与生态演进
  • 2026年3月光伏承包厂家推荐:聚焦全案资质与落地交付能力 - 品牌鉴赏师
  • 细聊实验室建设大会2026,国际科学仪器展选购设备有啥技巧? - 工业品牌热点
  • IIS管理器打开全攻略:从基础入门到高效运维
  • 细聊靠谱的检查井厂家哪家强,井通建材在上海地区值得推荐吗? - mypinpai
  • P10413 [蓝桥杯 2023 国 A] 圆上的连线 题解
  • 2026年口碑好的双机联动折弯机/折弯机制造厂家哪家靠谱 - 品牌宣传支持者
  • flutter组件学习之Padding 组件详解
  • 2026年3月双流灭臭虫公司推荐,精准检测与防治效果深度解析 - 品牌鉴赏师
  • MX播放器 2.9.0 | 安卓解码最强的媒体播放器,兼容特效字幕
  • 2026年3月双流灭白蚁公司推荐,精准检测与防治效果深度解析 - 品牌鉴赏师
  • PiliPlus 2.0.0 | 基于Flutter开发的第三方哔哩,目前最好用的一款
  • 深入Django模板引擎:揭开渲染魔法背后的API设计
  • 2026年3月双流灭蟑螂公司推荐,精准检测与防治效果深度解析 - 品牌鉴赏师
  • 2026年3月苏州高端装修公司推荐,资质案例售后机构深度解读 - 品牌鉴赏师
  • 2026年3月成都灭鼠公司最新推荐,聚焦定制消杀与全案解决方案 - 品牌鉴赏师
  • SQL 的 WHERE 子句的庖丁解牛
  • 2026年知名的液压式校平机/六重校平机正规生产厂家推荐 - 品牌宣传支持者
  • rust-edition-guide-l10n
  • 2026年3月苏州本帮菜美食店最新推荐,聚焦特色菜品与用餐体验 - 品牌鉴赏师
  • Azure DevOps Server:使用团队日历