SoFunction
Updated on 2025-03-01

Android floating window implementation principle and code example

1. The principle of implementation of floating windows

You can see the small Android icon in the picture above. It will not be blocked by other components, and can also respond to user clicks and drag events. Its display and disappearance are directly managed by WindowManager, which is an Android floating window. The implementation of Android floating windows mainly relies on the WindowManager class. Through the methods of addView(), updateViewLayout(), and removeView() of the WindowManager class, we can directly add, update and remove Views in the Window.

2. Specific steps to implement floating windows

1) Since the implementation of floating windows depends on WindowManager, there is no doubt that we have to get the WindowManger object first. Considering that floating windows are usually displayed after the application exits, we need to add and update floating windows in the Service. Of course, don’t forget to provide the user with a function of canceling floating windows.

2) Define the View you want to display. You can define it in the layout file or you can customize the views.

3) Set necessary parameters, and there are several more important parameters that need to be set. Please refer to the following code for details.

4) Add View to Window, receive and process events, and update View.

5) Add corresponding permissions to Manifest. <uses-permission android:name=".SYSTEM_ALERT_WINDOW"/>

3. Floating window implementation code

 package ;
 import ;
 import ;
 import ;
 import ;
 import ;
 import ;
 import ;
 import ;
 import ;
 import ;
 import ;

 public class FloatWindowService extends Service {

  private static final TAG = "FloatWindowService";

  private WindowManager mWindowManager;
  private  mLayoutParams;
  private LayoutInflater mLayoutInflater;
  private View mFloatView;
  private int mCurrentX;
  private int mCurrentY;
  private static int mFloatViewWidth = 50;
  private static int mFloatViewHeight = 80;
  @Override
  public void onCreate() {
    // TODO Auto-generated method stub
    ();
    //Initialize WindowManager object and LayoutInflater object    mWindowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
    mLayoutInflater = (this);
  }
  @Override
  public void onStart(Intent intent, int startId) {
    // TODO Auto-generated method stub
    (intent, startId);
    (TAG, "onStart()");
    createView();
  }
  private void createView() {
    // TODO Auto-generated method stub
    //Load the layout file    mFloatView = (, null);
    //Set up listening for View to handle user clicks and drags    (new OnFloatViewTouchListener());
    /*Set parameters for View*/
    mLayoutParams = new ();
    //Set the default placement position of the View     =  | ;
    //Set window type     = .TYPE_PHONE;
    //Set the background to transparent     = PixelFormat.RGBA_8888;
    //Note that the setting of this property is very important. FLAG_NOT_FOCUSABLE makes the floating window not get the focus. If this property is not set, clicking on other locations of the screen should be invalid, so they cannot get the focus.     = .FLAG_NOT_FOCUSABLE;
    //Set the display position of the view. Updating the view through WindowManager is actually changing the value of (x,y)    mCurrentX =  = 50;
    mCurrentY =  = 50;
    //Set the width and height of the view     = 100;
     = 100;
    //Add views to Window    (mFloatView, mLayoutParams);
  }
  /*Because the startService() is directly, this method is useless*/
  @Override
  public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
  }
  /*This method is used to update the position of the view, which is actually changing the value of (,)*/
  private void updateFloatView() {
     = mCurrentX;
     = mCurrentY;
    (mFloatView, mLayoutParams);
  }
  /* Handle the drag of the view. Only the Move event is processed here. Users can also handle click events. For example: when clicking on a floating window, start the main activity of the application*/
  private class OnFloatViewTouchListener implements  {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      // TODO Auto-generated method stub
      (TAG, "mCurrentX: " + mCurrentX + ",mCurrentY: "
          + mCurrentY + ",mFloatViewWidth: " + mFloatViewWidth
          + ",mFloatViewHeight: " + mFloatViewHeight);
      /*
        * getRawX() and getRawY() are very important.  Usually, we use getX() and getY() to get the trigger point coordinates of the event.
        * But getX() and getY() get the coordinates of the event trigger point relative to the upper left corner of the view; getRawX() and getRawY() get the event trigger point
        * Relative to the coordinates with the upper left corner of the screen.  Since x and y in LayoutParams are relative to the screen, you need to use getRawX() and getRawY().
        */
      mCurrentX = (int) () - mFloatViewWidth;
      mCurrentY = (int) () - mFloatViewHeight;
      int action = ();
      switch (action) {
      case MotionEvent.ACTION_DOWN:
        break;
      case MotionEvent.ACTION_MOVE:
        updateFloatView();
        break;
      case MotionEvent.ACTION_UP:
        break;
      }
      return true;
    }
  }
 }

4. How to display floating windows only in Launcher interface

Everyone should be familiar with the floating window of 360 Security Guard. Its floating window will only be displayed on the Launcher interface. When the user cuts to other interfaces, the floating window will be automatically removed.

To implement this function, we must know the current interface. If we only listen to the category of the Activity, then we can only know when we have entered the Launcher interface, but we cannot know whether we have left the Launcher interface. So how does 360 implement this function? You can decompile its code. Here is a feasible method. Our current situation is actually very simple, which is to know whether the current activity is the activity of the Launcher interface. Since the activity is managed as a stack, we just need to check whether the activity on the top of the stack is the Launcher's Activity. To obtain the Task information of the Activity, you need to add the corresponding permissions in the Manifest, <uses-permission android:name = ".GET_TASKS"/>.

private String getTopActivity(Context context) {
   //Get ActivityManager object   ActivityManager manager = (ActivityManager)getSystemService(ACTIVITY_SERVICE) ;
   /*
    * Get the currently running Task list, which is arranged in the order of the most recently used time, and the parameters represent the maximum number of list items to be returned.
    * Here we only need to get the Task where the Activity is in the onResume state is located.
    */
   List&lt;RunningTaskInfo&gt; runningTaskInfos = (1) ;
   if(runningTaskInfos != null) {
     //Get the stack top activity in the task     return ((0).topActivity).toString() ;
   } else {
     return null;
   }
 }

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.