Android如何仿IOS系统实现悬浮窗效果
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍Android如何仿IOS系统实现悬浮窗效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!代码如下:在这之前,我们需要在manifest中申请权限:并且,悬浮窗
千家信息网最后更新 2026年11月01日Android如何仿IOS系统实现悬浮窗效果
这篇文章主要介绍Android如何仿IOS系统实现悬浮窗效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
代码如下:
在这之前,我们需要在manifest中申请权限:
并且,悬浮窗这个权限我们需要手动在手机找到应用权限管理,允许这个权限才行
小悬浮窗的界面代码float_normal_view.xml:
大悬浮窗的界面代码float_control_view:
入口activity(FloatActivity ):
public class FloatActivity extends Activity { MyWindowManager myWindowManager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myWindowManager = MyWindowManager.getInstance(); myWindowManager.createNormalView(this.getApplicationContext()); }}悬浮窗管理器MyWindowManager:
/** * Created by shiweixian on 2017/3/7. * 悬浮窗管理器 * 创建,移除 * 单例模式 */public class MyWindowManager { private FloatNormalView normalView; private FloatControlView controlView; private static MyWindowManager instance; private WindowManager windowManager; private MyWindowManager() { } public static MyWindowManager getInstance() { if (instance == null) instance = new MyWindowManager(); return instance; } private WindowManager getWindowManager(Context context) { if (windowManager == null) windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); return windowManager; } /** * 判断小悬浮窗是否存在 * * @return */ public boolean isNormalViewExists() { return normalView != null; } /** * 判断播放器这个大悬浮窗是否存在 * * @return */ public boolean isControlViewExists() { return controlView != null; } /** * 创建小型悬浮窗 */ public void createNormalView(Context context) { if (normalView == null) { normalView = new FloatNormalView(context); } } /** * 移除悬浮窗 * * @param context */ public void removeNormalView(Context context) { if (normalView != null) { windowManager.removeView(normalView); normalView = null; } } /** * 创建小型悬浮窗 */ public void createControlView(Context context) { if (controlView == null) controlView = new FloatControlView(context); } /** * 移除悬浮窗 * * @param context */ public void removeControlView(Context context) { if (controlView != null) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); windowManager.removeView(controlView); controlView = null; } }}小悬浮窗FloatNormalView:
/** * Created by shiwe on 2017/3/7. * 缩小的悬浮窗 */public class FloatNormalView extends LinearLayout { /** * 记录小悬浮窗的宽度 */ public static int viewWidth; /** * 记录小悬浮窗的高度 */ public static int viewHeight; /** * 记录系统状态栏的高度 */ private static int statusBarHeight; /** * 用于更新小悬浮窗的位置 */ private WindowManager windowManager; /** * 小悬浮窗的参数 */ private WindowManager.LayoutParams mParams; /** * 记录当前手指位置在屏幕上的横坐标值 */ private float xInScreen; /** * 记录当前手指位置在屏幕上的纵坐标值 */ private float yInScreen; /** * 记录手指按下时在屏幕上的横坐标的值 */ private float xDownInScreen; /** * 记录手指按下时在屏幕上的纵坐标的值 */ private float yDownInScreen; /** * 记录手指按下时在小悬浮窗的View上的横坐标的值 */ private float xInView; /** * 记录手指按下时在小悬浮窗的View上的纵坐标的值 */ private float yInView; public FloatNormalView(Context context) { super(context); windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); LayoutInflater.from(context).inflate(R.layout.float_normal_view, this); View view = findViewById(R.id.ll_float_normal); viewWidth = view.getLayoutParams().width; viewHeight = view.getLayoutParams().height; initLayoutParams(); } /** * 初始化参数 */ private void initLayoutParams() { //屏幕宽高 int screenWidth = windowManager.getDefaultDisplay().getWidth(); int screenHeight = windowManager.getDefaultDisplay().getHeight(); mParams = new WindowManager.LayoutParams(); //总是出现在应用程序窗口之上。 mParams.type = WindowManager.LayoutParams.TYPE_PHONE; // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口 // FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按,不设置这个flag的话,home页的划屏会有问题 mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; //悬浮窗默认显示的位置 mParams.gravity = Gravity.START | Gravity.TOP; //指定位置 mParams.x = screenWidth - viewWidth * 2; mParams.y = screenHeight / 2 + viewHeight * 2; //悬浮窗的宽高 mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mParams.format = PixelFormat.TRANSPARENT; windowManager.addView(this, mParams); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度 xInView = event.getX(); yInView = event.getY(); xDownInScreen = event.getRawX(); yDownInScreen = event.getRawY() - getStatusBarHeight(); xInScreen = event.getRawX(); yInScreen = event.getRawY() - getStatusBarHeight(); break; case MotionEvent.ACTION_MOVE: xInScreen = event.getRawX(); yInScreen = event.getRawY() - getStatusBarHeight(); // 手指移动的时候更新小悬浮窗的位置 updateViewPosition(); break; case MotionEvent.ACTION_UP: // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) { openOrCloseControlView(); } break; default: break; } return true; } /** * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。 * * @param params 小悬浮窗的参数 */ public void setParams(WindowManager.LayoutParams params) { mParams = params; } /** * 更新小悬浮窗在屏幕中的位置。 */ private void updateViewPosition() { mParams.x = (int) (xInScreen - xInView); mParams.y = (int) (yInScreen - yInView); windowManager.updateViewLayout(this, mParams); } /** * 打开或关闭大悬浮窗。 */ private void openOrCloseControlView() { MyWindowManager manager = MyWindowManager.getInstance(); if (!manager.isControlViewExists()) manager.createControlView(getContext()); else manager.removeControlView(getContext()); } /** * 用于获取状态栏的高度。 * * @return 返回状态栏高度的像素值。 */ private int getStatusBarHeight() { if (statusBarHeight == 0) { try { Class> c = Class.forName("com.android.internal.R$dimen"); Object o = c.newInstance(); Field field = c.getField("status_bar_height"); int x = (Integer) field.get(o); statusBarHeight = getResources().getDimensionPixelSize(x); } catch (Exception e) { e.printStackTrace(); } } return statusBarHeight; }}大悬浮窗FloatControlView:
/** * Created by shiwe on 2017/3/7. * 缩小的悬浮窗 */public class FloatNormalView extends LinearLayout { /** * 记录小悬浮窗的宽度 */ public static int viewWidth; /** * 记录小悬浮窗的高度 */ public static int viewHeight; /** * 记录系统状态栏的高度 */ private static int statusBarHeight; /** * 用于更新小悬浮窗的位置 */ private WindowManager windowManager; /** * 小悬浮窗的参数 */ private WindowManager.LayoutParams mParams; /** * 记录当前手指位置在屏幕上的横坐标值 */ private float xInScreen; /** * 记录当前手指位置在屏幕上的纵坐标值 */ private float yInScreen; /** * 记录手指按下时在屏幕上的横坐标的值 */ private float xDownInScreen; /** * 记录手指按下时在屏幕上的纵坐标的值 */ private float yDownInScreen; /** * 记录手指按下时在小悬浮窗的View上的横坐标的值 */ private float xInView; /** * 记录手指按下时在小悬浮窗的View上的纵坐标的值 */ private float yInView; public FloatNormalView(Context context) { super(context); windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); LayoutInflater.from(context).inflate(R.layout.float_normal_view, this); View view = findViewById(R.id.ll_float_normal); viewWidth = view.getLayoutParams().width; viewHeight = view.getLayoutParams().height; initLayoutParams(); } /** * 初始化参数 */ private void initLayoutParams() { //屏幕宽高 int screenWidth = windowManager.getDefaultDisplay().getWidth(); int screenHeight = windowManager.getDefaultDisplay().getHeight(); mParams = new WindowManager.LayoutParams(); //总是出现在应用程序窗口之上。 mParams.type = WindowManager.LayoutParams.TYPE_PHONE; // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口 // FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按,不设置这个flag的话,home页的划屏会有问题 mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; //悬浮窗默认显示的位置 mParams.gravity = Gravity.START | Gravity.TOP; //指定位置 mParams.x = screenWidth - viewWidth * 2; mParams.y = screenHeight / 2 + viewHeight * 2; //悬浮窗的宽高 mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mParams.format = PixelFormat.TRANSPARENT; windowManager.addView(this, mParams); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度 xInView = event.getX(); yInView = event.getY(); xDownInScreen = event.getRawX(); yDownInScreen = event.getRawY() - getStatusBarHeight(); xInScreen = event.getRawX(); yInScreen = event.getRawY() - getStatusBarHeight(); break; case MotionEvent.ACTION_MOVE: xInScreen = event.getRawX(); yInScreen = event.getRawY() - getStatusBarHeight(); // 手指移动的时候更新小悬浮窗的位置 updateViewPosition(); break; case MotionEvent.ACTION_UP: // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) { openOrCloseControlView(); } break; default: break; } return true; } /** * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。 * * @param params 小悬浮窗的参数 */ public void setParams(WindowManager.LayoutParams params) { mParams = params; } /** * 更新小悬浮窗在屏幕中的位置。 */ private void updateViewPosition() { mParams.x = (int) (xInScreen - xInView); mParams.y = (int) (yInScreen - yInView); windowManager.updateViewLayout(this, mParams); } /** * 打开或关闭大悬浮窗。 */ private void openOrCloseControlView() { MyWindowManager manager = MyWindowManager.getInstance(); if (!manager.isControlViewExists()) manager.createControlView(getContext()); else manager.removeControlView(getContext()); } /** * 用于获取状态栏的高度。 * * @return 返回状态栏高度的像素值。 */ private int getStatusBarHeight() { if (statusBarHeight == 0) { try { Class> c = Class.forName("com.android.internal.R$dimen"); Object o = c.newInstance(); Field field = c.getField("status_bar_height"); int x = (Integer) field.get(o); statusBarHeight = getResources().getDimensionPixelSize(x); } catch (Exception e) { e.printStackTrace(); } } return statusBarHeight; }}以上是"Android如何仿IOS系统实现悬浮窗效果"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!
手指
位置
屏幕
高度
参数
状态
纵坐标
更新
横坐标
应用
系统
事件
权限
代码
管理
效果
必要
像素
内容
图标
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
科技互联网产品
互联网科技官网
互联网科技股票
中国互联网科技发展
广州宏创互联网科技
互联网女皇 腾讯科技
时间互联网络科技
奔汉互联网科技
深圳天众互联网科技公司
互联网科技大会
哈尔滨新华互联网科技
互联网科技实习生岗位职责
金融科技与互联网金融相同和不同
江阴互联网智能科技产品进口
移动互联网年度科技创新
高科技互联网套路
江苏互联网科技小贷
科技互联网专业工作会议发言稿
武汉亿视互联网科技有限公司
互联网 科技节活动 微视频大赛
互联网科技工作委员会副主任毛军
互联网科技深圳
互联网科技开发公司
农村开互联网科技讲堂
成都互联网科技公司100强
广州市恰铎互联网科技有限公司
互联网科技研发水平
沐思想互联网科技有限公司
东营紫格互联网科技
广州梦谷互联网科技有限公司领导