目录 Android 界面绘制都是通过 WindowManager 服务来实现的,WindowManager 对象可通过获取 WINDOW_SERVICE 系统服务得到,并因为 WindowManager 继承于 ViewManager ,所以其拥有以下方法 addView(View view, ViewGroup.LayoutParams params) 主要通过该方法将指定 View 添加到屏幕上,实现悬浮窗效果 ( WindowManager 对象调用 addView( ) 入参的 LayoutParams 必须为 WindowManager.LayoutParams ) 移除指定已添加到屏幕上的 View updateViewLayout(View view, ViewGroup.LayoutParams params) 通过调整 LayoutParams 更新屏幕上的指定 View 1)在 AndroidManifest 中声明权限 2)判断是否拥有在屏幕上层绘制权限 3)获取 WindowManager 对象,生成 WindowManager.LayoutParams ,调用 addView 方法传入指定 View MainActivity 代码(Kotlin,点击查看源码) ExampleFloatingService 代码(Kotlin,点击查看源码) 悬浮窗管理服务,一般在此处理业务逻辑 目的脱离 Activity 展示悬浮窗 帮助类 FloatingWindowHelper(Java,点击查看源码) 悬浮窗功能相关操作帮助类,使用示例如下 需求分析: 1.悬浮可拖动 2.自动粘边:停留时只粘在屏幕左边或右边 3.圆直角切换:拖动时悬浮窗四个角为圆角,粘边时粘边处皆为直角 1.悬浮可拖动 通过 WindowManager addView 实现悬浮效果 通过重写悬浮 View 的 onTouch 方法或为悬浮 View setOnTouchListener 处理触摸事件记录滑动距离,再通过 WindowManager updateViewLayout 方法更新悬浮 View 位置,实现悬浮可拖动效果 2.自动粘边:停留时只粘在屏幕左边或右边 重写悬浮 View 的 onTouch 方法感知触摸事件,当处于触摸移动状态时,更新悬浮 View 四周角为圆角。当触摸抬起时,根据悬浮 View 当前坐标与屏幕宽度值判断位置,然后通过 WindowManager updateViewLayout 方法更新悬浮 View 位置,将悬浮 View 平移到屏幕坐标或右边,实现粘边效果 3.圆直角切换:拖动时悬浮窗四个角为圆角,粘边时粘边处皆为直角 重写悬浮 View 的 onDraw 方法,根据移动方向判断是否需要在左/右边绘制直角矩形覆盖圆角,实现圆直角切换效果 4. 代码示例 调用(Kotlin)
1.基本介绍
2.代码示例
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
/** * 判断是否拥有悬浮窗权限 * * @param isApplyAuthorization 是否申请权限 */ public static boolean canDrawOverlays(Context context, boolean isApplyAuthorization) { //Android 6.0 以下无需申请权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //判断是否拥有悬浮窗权限,无则跳转悬浮窗权限授权页面 if (Settings.canDrawOverlays(context)) { return true; } else { if (isApplyAuthorization) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); if (context instanceof Service) { intent.setFlags(FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); return false; } else { return false; } } } else { return true; } }
//获取 WindowManager 服务 WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE); //生成 WindowManager.LayoutParams 对象 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); //形成的窗口层级关系,Android 8.0 前后存在区别 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.START | Gravity.TOP; //该flags描述的是窗口的模式,是否可以触摸,可以聚焦等 layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; //窗口宽高 layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT; layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT; //需要悬浮的指定 View View view = LayoutInflater.from(context).inflate(R.layout.widget_test_view, null, false); //将指定 View 添加到屏幕上 windowManager.addView(view, layoutParams);
3.实现效果及便捷工具类
btn_show_view.setOnClickListener { if (ExampleFloatingService.isStart) { //通知处理点击事件 LocalBroadcastManager.getInstance(this) .sendBroadcast(Intent(ExampleFloatingService.ACTION_CLICK)) } else { if (FloatingWindowHelper.canDrawOverlays(this, true)) { startService(Intent(this, ExampleFloatingService::class.java)) } } }
private lateinit var mFloatingWindowHelper: FloatingWindowHelper private lateinit var mExampleViewA: View private lateinit var mExampleViewB: View override fun onCreate() { super.onCreate() mFloatingWindowHelper = FloatingWindowHelper(this) val layoutInflater = LayoutInflater.from(this) mExampleViewA = layoutInflater.inflate(R.layout.widget_test_view, null, false) mExampleViewB = layoutInflater.inflate(R.layout.widget_test_view_b, null, false) } private fun onClick() { if (!mFloatingWindowHelper.contains(mExampleViewA)) { //悬浮显示指定 View mFloatingWindowHelper.addView(mExampleViewA) } else if (!mFloatingWindowHelper.contains(mExampleViewB)) { //悬浮显示指定 View 在指定位置,并可拖动 mFloatingWindowHelper.addView(mExampleViewB, 100, 100, true) } else { //移除所有悬浮 View mFloatingWindowHelper.clear() } } override fun onDestroy() { mFloatingWindowHelper.destroy() super.onDestroy() }
4.仿微信语音通话悬浮窗效果实现
4.1 需求分析及效果展示
4.2 实现
val voiceFloatingView = VoiceFloatingView(context) voiceFloatingView.show()
5.最后
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算