SoFunction
Updated on 2025-04-09

Android Custom APP Global Floating Button

I originally wanted to implement a button suspended on other controls through framelayout, but I felt it was very troublesome and needed to dynamically fill each interface. So when I thought of the floating window, I customized an ImageView to display the global button.

1. First of all, because of the floating window type, you need to add permissions. For SDK>=23, you need to obtain permissions dynamically. I use 22 here.

 <uses-permission android:name=".SYSTEM_ALERT_WINDOW" />
  <uses-permission android:name=".WRITE_SETTINGS"/>

2. Obtain the global WindowManager params data through application

 private  wmParams=new ();
  public  getMywmParams(){
    return wmParams;
  }

3. Customize the ImageView and realize the status selection of clicks. A callback interface is written for processing click events.

public class CustomeMovebutton extends ImageView {
  private final int statusHeight;
  int sW;
  int sH;
  private float mTouchStartX;
  private float mTouchStartY;
  private float x;
  private float y;
  private boolean isMove=false;
  private Context context;
  private WindowManager wm = (WindowManager) getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
  private  wmParams = ((MyApplication) getContext().getApplicationContext()).getMywmParams();
  private float mLastX;
  private float mLastY;
  private float mStartX;
  private float mStartY;
  private long mDownTime;
  private long mUpTime;
  private OnSpeakListener listener;

  public CustomeMovebutton(Context context) {
    this(context,null);
     = context;
  }
  public CustomeMovebutton(Context context, AttributeSet attrs) {
    this(context, attrs,-1);
  }
  public CustomeMovebutton(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs,defStyleAttr);
    sW = ().getWidth();
    sH = ().getHeight();
    statusHeight = getStatusHeight(context);
  }

  /**
    * The height of the status bar
    *
    */
  public static int getStatusHeight(Context context) {
    int statusHeight = -1;
    try {
      Class clazz = ("$dimen");  //Use reflection to get instance      Object object = ();
      int height = (("status_bar_height")
          .get(object).toString());
      statusHeight = ().getDimensionPixelSize(height);
    } catch (Exception e) {
      ();
    }
    return statusHeight;
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    //Get the coordinates of the relative screen, that is, use the upper left corner of the screen as the origin point    x = ();
    y = () - statusHeight;  //statusHeight is the height of the system status bar    switch (()) {
      case MotionEvent.ACTION_DOWN:  //Press        setImageResource(.btn_voice_pressed);
        mTouchStartX = ();
        mTouchStartY = ();
        mStartX = ();
        mStartY = ();
        mDownTime = ();
        isMove = false;
        break;
      case MotionEvent.ACTION_MOVE:  //Finger movement        updateViewPosition();
        isMove = true;
        break;
      case MotionEvent.ACTION_UP:  //Release your hand        setImageResource(.btn_voice_rest);
        mLastX = ();
        mLastY = ();
        mUpTime = ();
        //The time it takes to press to lift is greater than 500 milliseconds, and the absolute value of lift is greater than 20 pixels to handle click event        if(mUpTime - mDownTime &lt; 500){
          if((mStartX- mLastX )&lt; 20.0 &amp;&amp; (mStartY - mLastY) &lt; 20.0){
              if (listener!=null){
                ();
              }
          }
        }

        break;
    }
    return true;
  }

  private void updateViewPosition() {
     = (int) (x - mTouchStartX);
     = (int) (y- mTouchStartY);
    (this, wmParams); //Refresh the display  }

  /**
    * Set the click callback interface
    */
  public interface OnSpeakListener{
    void onSpeakListener();
  }
  public void setOnSpeakListener(OnSpeakListener listener){
    =listener;
  }
}

4. Used in Activity, which includes setting the parameters and position parameters of the picture

public class MainActivity extends AppCompatActivity{

  private WindowManager wm;
  private  wmParams;
  private CustomeMovebutton CustomeMovebutton;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    (savedInstanceState);
    setContentView(.activity_main);
    wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics dm = getResources().getDisplayMetrics();
    int widthPixels = ;
    int heightPixels = ;
    wmParams = ((MyApplication) getApplication()).getMywmParams();
     = .TYPE_SYSTEM_ALERT;
    = PixelFormat.RGBA_8888;//Set background pictures    = .FLAG_NOT_TOUCH_MODAL | .FLAG_NOT_FOCUSABLE ;//
     = |;//
     = widthPixels-150;  //Set position pixel     = heightPixels-110;
    =200; //Set the image size    =200;
    CustomeMovebutton = new CustomeMovebutton(getApplicationContext());
    (.btn_voice_rest);
    (CustomeMovebutton, wmParams);
    (new () {
      @Override
      public void onSpeakListener() {
        (, "Click Event", Toast.LENGTH_SHORT).show();
      }
    });
  }

  @Override
  protected void onDestroy() {
    ();
    if(CustomeMovebutton != null){
      (CustomeMovebutton);
    }
  }
}

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.