Android使用WindowManager构造悬浮view

一般在android显示一个View都是通过Activity的setContentView设置的,但是还有一种方法,可以直接使用WindowManager在整个应用的最上层绘制我们需要显示的view,总体的效果类似于AlertDialog的弹出效果。

使用WindowManager构造这样的一个悬浮View也比较简单,直接通过windowmanager.addView()方法即可。

package com.gearmotion.app.windowmanagermotion;

import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {

 Button mShowBtn;
 Button mHideBtn;
 WindowManager mWm;
 LayoutInflater mLayoutInflater;
 View mWindowView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mShowBtn = (Button) this.findViewById(R.id.showbtn);
  mHideBtn = (Button) this.findViewById(R.id.hidebtn);
  mShowBtn.setOnClickListener(this);
  mHideBtn.setOnClickListener(this);
  init();
 }

 private void init() {
  mWm = (WindowManager) this.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
  mLayoutInflater = LayoutInflater.from(this);
 }

 @Override
 public void onClick(View v) {
  if (mShowBtn.hashCode() == v.hashCode()) { //显示WindowManager
   show();
  }
  if (mHideBtn.hashCode() == v.hashCode()) { //隐藏windowmanager
   hide();
  }
 }

 private void show() {
  mWindowView = mLayoutInflater.inflate(R.layout.item_layout, null);
  View popView = mWindowView.findViewById(R.id.root);
  //设置popView的触摸事件,以便点击空白区域的时候使悬浮view消失
  popView.setOnTouchListener(this);
  WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
  //窗口类型同系统弹出框
  lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
  //响应输入法
  //lp.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
  //透明层
  lp.format = PixelFormat.TRANSPARENT;
  lp.width = WindowManager.LayoutParams.MATCH_PARENT;
  lp.height = WindowManager.LayoutParams.MATCH_PARENT;
  lp.gravity = Gravity.CENTER_VERTICAL;
  mWm.addView(mWindowView, lp);
 }

 private void hide() {
  if (mWindowView != null && mWindowView.getParent() != null) {
   mWm.removeView(mWindowView);
  }
 }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  int x = (int) event.getX();
  int y = (int) event.getY();
  //获取主view的可视区域
  Rect globalRect = new Rect();
  //获取悬浮view的可视区域
  Rect tmpRect = new Rect();
  v.getGlobalVisibleRect(globalRect);
  View child = ((ViewGroup) v).getChildAt(0);
  child.getHitRect(tmpRect);
  if (!tmpRect.contains(x, y) && globalRect.contains(x, y)) {
   hide();
  }
  return true;
 }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity">

 <Button
  android:id="@+id/showbtn"
  android:layout_width="match_parent"
  android:layout_height="50dp"
  android:gravity="center"
  android:text="show" />

 <Button
  android:id="@+id/hidebtn"
  android:layout_width="match_parent"
  android:layout_height="50dp"
  android:gravity="center"
  android:text="hide" />
</LinearLayout>

item_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:id="@+id/root"
 android:orientation="vertical">

 <TextView
  android:layout_width="match_parent"
  android:layout_height="50dp"
  android:text="I am WindowManager layout view"
  android:textSize="20sp"
  android:gravity="center"
  android:layout_gravity="center"
  android:background="#FFF8DC"
  android:textColor="#7AC5CD"/>
</LinearLayout>

实现效果如下:

以上就是本文的全部内容,希望对大家学习Android有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 通过案例分析Android WindowManager解析与骗取QQ密码的过程

    Windows Manager是一款窗口管理终端,可以远程连接到Linux的X桌面进行管理,与服务器端产生一个session相互通信. 最近在网上看见一个人在乌云上提了一个漏洞,应用可以开启一个后台Service,检测当前顶部应用,如果为QQ或相关应用,就弹出一个自定义window用来诱骗用户输入账号密码,挺感兴趣的,总结相关知识写了一个demo,界面如下(界面粗糙,应该没人会上当吧,意思到了就行哈=, =): Window&&WindowManager介绍 分析demo之前,先要整理总结

  • 深入理解Android中的Window和WindowManager

    Window表示一个窗口的概念,Window是一个抽象类,它的具体实现是PhoneWindow.创建一个Window,需要通过WindowManager即可完成,WindowManager是外界访问Window的入口,Window具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC的过程.Android中,所有的视图都是通过Window来呈现,不管是Activity.Dialog.还是Toast,它们的视图

  • Android利用WindowManager生成悬浮按钮及悬浮菜单

    简介 本文模仿实现的是360手机卫士基础效果,同时后续会补充一些WindowManager的原理知识. 整体思路 360手机卫士的内存球其实就是一个没有画面的应用程序,整个应用程序的主体是一个Service.我们的程序开始以后,启动一个service,同时关闭activity即可: public class MainActivity extends Activity { private static final String TAG = MainActivity.class.getSimpleN

  • Android使用WindowManager制作一个可拖动的控件

    效果图如下 第一步:新建DragView继承RelativeLayout package com.rong.activity; import com.rong.test.R; import android.content.Context; import android.graphics.Color; import android.graphics.PixelFormat; import android.util.AttributeSet; import android.view.Gravity;

  • WindowManagerService服务是如何以堆栈的形式来组织窗口

    我们知道,在Android系统中,Activity是以堆栈的形式组织在ActivityManagerService服务中的.与Activity类似,Android系统中的窗口也是以堆栈的形式组织在WindowManagerService服务中的,其中,Z轴位置较低的窗口位于Z轴位置较高的窗口的下面.在本文中,我们就详细分析WindowManagerService服务是如何以堆栈的形式来组织窗口的. 从前面Android应用程序启动过程源代码分析一文可以知道,应用程序进程中的每一个Activity

  • 在当前Activity之上创建悬浮view之WindowManager悬浮窗效果

    最近有学生做毕业设计,想使用悬浮窗这种效果,其实很简单,我们可以通过系统服务WindowManager来实现此功能,本章我们来试验一下在当前Activity之上创建一个悬浮的view. 第一步:认识WindowManager 这个接口用于与 window manager (窗口管理器, 应用框架层) 进行交互. 通过getSystemService(Context.WINDOW_SERVICE)可以获取到WM的实例. 继承关系 public interface WindowManager imp

  • Android使用WindowManager构造悬浮view

    一般在android显示一个View都是通过Activity的setContentView设置的,但是还有一种方法,可以直接使用WindowManager在整个应用的最上层绘制我们需要显示的view,总体的效果类似于AlertDialog的弹出效果. 使用WindowManager构造这样的一个悬浮View也比较简单,直接通过windowmanager.addView()方法即可. package com.gearmotion.app.windowmanagermotion; import an

  • Android利用WindowManager实现悬浮窗

    前言 你会发现QQ视频的时候,就算手机回到主页,视频小模块依旧能悬浮在桌面上.还有当年很火的各种手机杀毒软件的桌面小助手,总能在呆在桌面.这种悬浮窗的操作就需要用到Window. 效果 gif图看着有点儿卡,其实实际上还是很流畅的. Window Window即窗口,是个抽象类,具体实现就是PhoneWindow,对就是那个装着DecorView的PhoneWindow. Window整体分三种类型:应用Window.子Window.系统Window. 应用Window:对应一个Activity

  • Android自定义APP全局悬浮按钮

    原本想通过framelayout实现一个悬浮在其他控件上的按钮,但是觉得很麻烦,需要各个界面都要动态填充.于是想到了悬浮窗,就自定一个ImageView用于显示全局按钮. 一.首先因为悬浮窗式的所以要添加权限,对于SDK>=23的需要动态获取权限,我这边用的是22的 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:

  • Android WindowManager深层理解view绘制实现流程

    目录 前言 setContentView()流程 WindowManager.addView流程 前言 又是一年一度的1024程序员节了,今天不写点什么总感觉对不起这个节日.想来想去,就写点关于View的绘制.本文不会重点讲View绘制三大回调函数:onMeasure.onLayout.onDraw,而是站在Android framework的角度去分析一下View的绘制. View是如何被渲染到屏幕中的? ViewRoot.DecorView.Activity.Window.WindowMan

  • Android实现系统级悬浮按钮

    本文实例为大家分享了Android系统级悬浮按钮的具体代码,供大家参考,具体内容如下 具体的需求 1.就是做一个系统级的悬浮按钮,就像iPhone 桌面的那个悬浮按钮效果一样,能随意拖动,并且手一放开,悬浮按钮就自动靠边. 2.可以点击并且可以随意拖动. 3.悬浮按钮自动靠边的时候,或者移动到边上的时候,自动隐藏半边. 4.横竖屏切换都兼容 1.就在WindowManager 里面添加View,这个View通过自定义控件来实现. 2.在onTouch里的MotionEvent.ACTION_MO

  • Android仿微信文章悬浮窗效果的实现代码

    序言 前些日子跟朋友聊天,朋友Z果粉,前些天更新了微信,说微信出了个好方便的功能啊,我问是啥功能啊,看看我大Android有没有,他说现在阅读公众号文章如果有人给你发微信你可以把这篇文章当作悬浮窗悬浮起来,方便你聊完天不用找继续阅读,听完是不是觉得这叫啥啊,我大Android微信版不是早就有这个功能了吗,我看文章的时候看到过有这个悬浮按钮,但是我一直没有使用过,试了一下还是挺方便的,就想着自己实现一下这个功能,下面看图,大家都习惯了无图言X 原理 看完动图我们来分析一下,如何在每个页面上都存在一

  • android实现桌面移动悬浮窗口

    现在很多应用都有这样的功能,比如360等安全卫士,手机管家之内的应用. 效果图: 一.实现原理及移动思路 调用WindowManager,并设置WindowManager.LayoutParams的相关属性,通过WindowManager的addView方法创建View,这样产生出来的View根据WindowManager.LayoutParams属性不同,效果也就不同了.比如创建系统顶级窗口,实现悬浮窗口效果!然后通过覆写悬浮View中onTouchEvent方法来改变windowManana

  • Android仿IOS系统悬浮窗效果

    在一些场合里,我们使用悬浮窗会有很大的便利,比如IOS系统的悬浮窗,360或者其他手机卫士的悬浮窗等等. 本篇博客,我们创造出两个悬浮窗,通过点击小悬浮窗打开或者关闭大悬浮窗(一个播放控制器). 代码如下: 在这之前,我们需要在manifest中申请权限: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 并且,悬浮窗这个权限我们需要手动在手机找到应用权限管理,允许这个权限才行

随机推荐