Related tags

Layout FloatingView


[Archived] Use instead: https://developer.android.com/guide/topics/ui/bubbles

The Android project is View to display information such as chat in front. To API Level 14 or higher are supported


Watch YouTube video


Target Sdk Version : 28
Min Sdk Version : 14

How to use

  1. Add this to your build.gradle.
repositories {
    maven {
        url "https://jitpack.io"

dependencies {
  implementation 'com.github.recruit-lifestyle:FloatingView:2.4.4'
  1. Implement Service for displaying FloatingView
public class ChatHeadService extends Service {
  ... ...
  1. You will do the setting of the View to be displayed in the FloatingView(Sample have a set in onStartCommand)
  final LayoutInflater inflater = LayoutInflater.from(this);
  final ImageView iconView = (ImageView) inflater.inflate(R.layout.widget_chathead, null, false);
  1. Use the FloatingViewManager, make the setting of FloatingView
  mFloatingViewManager = new FloatingViewManager(this, this);
  final FloatingViewManager.Options options = new FloatingViewManager.Options();
  options.overMargin = (int) (16 * metrics.density);
  mFloatingViewManager.addViewToWindow(iconView, options);

The second argument of FloatingViewManager is FloatingViewListener

Describe the process (onFinishFloatingView) that is called when you exit the FloatingView

    public void onFinishFloatingView() {
  1. Add the permission to AndroidManifest
 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  1. Define the Service to AndroidManifest


    <application ...>
        <!-- Demo -->
  1. Describe the process to start the Service (run on foreground)


  • FloatingViewControlFragment.java
    final Intent intent = new Intent(activity, ChatHeadService.class);
    ContextCompat.startForegroundService(activity, intent);
  • ChatHeadService.java
public int onStartCommand(Intent intent, int flags, int startId) {
    startForeground(NOTIFICATION_ID, createNotification(this));
  1. Create notification channel (targetSdkVersion >= 26)


    final String channelId = getString(R.string.default_floatingview_channel_id);
    final String channelName = getString(R.string.default_floatingview_channel_name);
    final NotificationChannel defaultChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_MIN);
    final NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    if (manager != null) {
  1. Add DisplayCutout process(API Level >= 28)

Call FloatingViewManager.findCutoutSafeArea(activity).
Note: Activity must be portrait oriented.
Note: You must not set windowLayoutInDisplayCutoutMode to never.


  • FloatingViewControlFragment.java
final Intent intent = new Intent(activity, ChatHeadService.class);
intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity));
ContextCompat.startForegroundService(activity, intent);
  • ChatHeadService.java
mFloatingViewManager.setSafeInsetRect((Rect) intent.getParcelableExtra(EXTRA_CUTOUT_SAFE_AREA));

Static Options

It can be set only when displaying for the first time


final FloatingViewManager.Options options = new FloatingViewManager.Options();
options.overMargin = (int) (16 * metrics.density);
mFloatingViewManager.addViewToWindow(iconView, options);
Option Description
shape FloatingViewManager.SHAPE_CIRCLE:Circle(default)
overMargin Margin over the edge of the screen (px)
(default) 0
floatingViewX X coordinate of initial display
(default) left side of display
floatingViewY Y coordinate of initial display
(default) top of display
floatingViewWidth FloatingView width
(default) The width of the layout added to FloatingView
floatingViewHeight FloatingView height
(default) The height of the layout added to FloatingView
moveDirection FloatingViewManager.MOVE_DIRECTION_DEFAULT:Left end or right end(default)
FloatingViewManager.MOVE_DIRECTION_LEFT:Left end
FloatingViewManager.MOVE_DIRECTION_RIGHT:Right end
FloatingViewManager.MOVE_DIRECTION_NONE:Not move
FloatingViewManager.MOVE_DIRECTION_NEAREST:Move nearest edge
FloatingViewManager.MOVE_DIRECTION_THROWN:Move in the throwing direction (left end or right end)
usePhysics Use physics-based animation(depends on moveDirection)
(default) true
Info:If MOVE_DIRECTION_NEAREST is set, nothing happens
Info:Can not be used before API 16
animateInitialMove If true, animation when first displayed
(FloatingViewX, floatingViewY) to screen edge
Info: If MOVE_DIRECTION_NONE is set, nothing happens

Dynamic Options

It can be set any time


Option Description
setFixedTrashIconImage It is an icon that does not enlarge when FloatingView overlaps.
setActionTrashIconImage It is an icon that enlarge when FloatingView overlaps.
setDisplayMode FloatingViewManager.DISPLAY_MODE_SHOW_ALWAYS:Always show
FloatingViewManager.DISPLAY_MODE_HIDE_ALWAYS:Always hidden
FloatingViewManager.DISPLAY_MODE_HIDE_FULLSCREEN:It is hidden when in full screen
setTrashViewEnabled If false, the trash icon does not show during dragging.
(default) true


FloatingView is owned and maintained by RECRUIT LIFESTYLE CO., LTD.

FloatingView was originally created by Yoshihide Sogawa



Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at


Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.
  • addViewToWindow() crashes with IllegalStateException

    addViewToWindow() crashes with IllegalStateException

    In our project we show and hide FloatingView programmatically (it should only be shown when app is in background). Unfortunately, sometimes FloatingViewManager.addViewToWindow() crashes with

    java.lang.IllegalStateException: View jp.co.recruit_lifestyle.android.floatingview.FullscreenObserverView{3ed8eb3e V.ED.... ......ID 0,0-1,1134} has already been added to the window manager.
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:253)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
        at jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager.addViewToWindow(FloatingViewManager.java:545)

    Catching this exception results in duplicated FloatingView, so this may be the same issue as #99. Version 2.3.2 did not have this issue, probably it was introduced while fixing #89.

    Sample project: FloatingViewTest.zip Issue is better reproduced with fast show/hide switching, but in real app I've seen a crash after >5 sec delay between hide and show.

    We've tried some workarounds, but without success: recreating FloatingViewManager on each cycle produces duplicate FloatingViews sometimes, and FloatingView.setVisibility(View.GONE) often leaves it visible.

    opened by gmk57 10
  • Laggy floatingview

    Laggy floatingview

    Floatingview is sometimes laggy. Other times works super smooth. And cant find any way to reproduce that will tell me why this happens. Isn't supposed to work smoothly all the time.?

    opened by mhackeras 8
  • FloatingView is to the right of the finger in landscape mode

    FloatingView is to the right of the finger in landscape mode

    1. Rotate your phone to landscape so that the NavBar is on the left.
    2. Make a "Simple FloatingView" appear in the FloatingView sample
    3. Try to move it

    The floatingview will not be under your finger. It is slightly to the right.

    opened by geecko86 7
  • Add Option to use dynamic physics-based animations (close #44)

    Add Option to use dynamic physics-based animations (close #44)

    Alright, I found a solution to correctly track velocity: you had to get the rawX and rawY coordinates from the motionevent.

    1. I added a new dependency: support-dynamic-animation NOTE: the minsdk for the library is still 14 but no change will be visible when using the lib on API < 16.
    2. I added an option (in the library and in the sample) to use Physics when throwing the FloatingView
    3. I added another option so that the FloatingView would go to the side where it is thrown. Formerly if it was on the left of the screen and you lifted your finger, it would go back to the left side. Now, if you throw it to the right with enough speed, it will go to the right side, etc.

    Here's a video to demonstrate it. The one with the mail icon is the one with the custom options. ➡➡➡ https://vid.me/SJvh

    And here's two screenshots from the options 1 2

    This does NOT in my opinon, solve issue #19.

    opened by geecko86 7
  • RelativeLayout with button

    RelativeLayout with button

    I trying to create the RelativeLayout class to replace the iconView

    final ImageView iconView = (ImageView) inflater.inflate(R.layout.widget_mail, null, false);

    like is

    final MapRelativeLayout mapView = new MapRelativeLayout(getApplicationContext());

    the mapView can show on screen, but the button OnClickListener is not working, How can I fix it?

    and there is my MapRelativeLayout class

    public class MapRelativeLayout extends RelativeLayout {
        LayoutInflater mInflater;
        public MapRelativeLayout(Context context){
            mInflater = LayoutInflater.from(context);
        public void init()
            View v = mInflater.inflate(R.layout.widget_map_relative_layout, this, true);
           Button btn = findViewById(R.id.button);
            btn.setOnClickListener(new OnClickListener() {
                public void onClick(View view) {
                    Log.d("TEST", "Testing");
    opened by tommyim 6
  • Supporting for a complicated view

    Supporting for a complicated view

    First of all, i'm sorry for posting here, i can't found your contact. Can you make it supports a complicated view. I'm using the library, and my view has some buttons, the problem is i can't click on any button. Thanks in advanced.

    opened by bqthuan 6
  • getDisplayCutout() on a null object reference

    getDisplayCutout() on a null object reference

    Hello i am getting this error:

    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.DisplayCutout android.view.WindowInsets.getDisplayCutout()' on a null object reference
    at jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager.findCutoutSafeArea(FloatingViewManager.java:618)

    I am starting a service like this:

    intent.putExtra(GraphHeadService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(this));
    ContextCompat.startForegroundService(this, intent);

    Is there any problem with FloatingViewManager.findCutoutSafeArea(this)?

    My GraphHeadService.java

    package in.graphhed.app;
    import android.app.Notification;
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.Rect;
    import android.os.IBinder;
    import android.support.v4.app.NotificationCompat;
    import android.util.DisplayMetrics;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.ImageView;
    import jp.co.recruit_lifestyle.android.floatingview.FloatingViewListener;
    import jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager;
    public class GraphHeadService extends Service implements FloatingViewListener {
        private FloatingViewManager mFloatingViewManager;
        private static final String TAG = "GraphHeadService";
        private static final int NOTIFICATION_ID = 5469;
        public static final String EXTRA_CUTOUT_SAFE_AREA = "cutout_safe_area";
        public GraphHeadService() {
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (mFloatingViewManager != null) {
                return START_STICKY;
            final DisplayMetrics metrics = new DisplayMetrics();
            final WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            final LayoutInflater inflater = LayoutInflater.from(this);
            final ImageView iconView = (ImageView) inflater.inflate(R.layout.layout_floating_widget, null, false);
            iconView.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    Log.d(TAG, "Chathead Clicked");
            mFloatingViewManager = new FloatingViewManager(this, this);
            mFloatingViewManager.setSafeInsetRect((Rect) intent.getParcelableExtra(EXTRA_CUTOUT_SAFE_AREA));
            final FloatingViewManager.Options options = new FloatingViewManager.Options();
            options.overMargin = (int) (16 * metrics.density);
            mFloatingViewManager.addViewToWindow(iconView, options);
            startForeground(NOTIFICATION_ID, createNotification(this));
            return START_REDELIVER_INTENT;
        public void onDestroy() {
        public void onFinishFloatingView() {
        public void onTouchFinished(boolean isFinishing, int x, int y) {
            if (isFinishing) {
                Log.d(TAG, "Deleting Soon");
            } else {
                Log.d(TAG, "Deleted "+ getString(x, y));
        private void destroy() {
            if (mFloatingViewManager != null) {
                mFloatingViewManager = null;
        private static Notification createNotification(Context context) {
            final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, context.getString(R.string.default_floatingview_channel_id));
            return builder.build();
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            throw new UnsupportedOperationException("Not yet implemented");

    and my DataReceiverActivity.java

    package in.graphhed.app;
    import android.content.Intent;
    import android.os.Build;
    import android.provider.Settings;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    import android.widget.Toast;
    import jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager;
    public class DataReceiverActivity extends AppCompatActivity {
        private TextView intentEcho;
        private static final int SYSTEM_ALERT_WINDOW_PERMISSION = 5469;
        protected void onCreate(Bundle savedInstanceState) {
            Intent receivedIntent = getIntent();
            String receivedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                Toast.makeText(this, "In App Viewer!", Toast.LENGTH_SHORT).show();
            } else if (Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(this, GraphHeadService.class);
                //intent.putExtra("url",  receivedText);
                intent.putExtra(GraphHeadService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(this));
                ContextCompat.startForegroundService(this, intent);
            } else {
                Toast.makeText(this, "In App Viewer!", Toast.LENGTH_SHORT).show();
    opened by sukhcha-in 5
  • Support Android P

    Support Android P

    branch https://github.com/recruit-lifestyle/FloatingView/tree/feature/support_p

    opened by YoshihideSogawa 5
  • Error when trying to close FloatingView by dragging it to bottom

    Error when trying to close FloatingView by dragging it to bottom

    Hi! First of all thanks for this great library, it's really awesome to use. However, when I try to drag chatHead(Floating view) to bottom(to close it) and after Floating View closes I get the following error:

    java.lang.IllegalArgumentException: View=jp.co.recruit_lifestyle.android.floatingview.FloatingView{79038e7 G.E...... ......ID 0,0-78,78} not attached to window manager
                                                                             at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:473)
                                                                             at android.view.WindowManagerGlobal.updateViewLayout(WindowManagerGlobal.java:368)
                                                                             at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:101)
                                                                             at jp.co.recruit_lifestyle.android.floatingview.FloatingView.updateViewLayout(FloatingView.java:507)
                                                                             at jp.co.recruit_lifestyle.android.floatingview.FloatingView.onUpdateSystemLayout(FloatingView.java:418)
                                                                             at jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager.onScreenChanged(FloatingViewManager.java:234)
                                                                             at jp.co.recruit_lifestyle.android.floatingview.FullscreenObserverView.onSystemUiVisibilityChange(FullscreenObserverView.java:129)
                                                                             at android.view.View.dispatchSystemUiVisibilityChanged(View.java:20483)
                                                                             at android.view.ViewRootImpl.handleDispatchSystemUiVisibilityChanged(ViewRootImpl.java:5622)
                                                                             at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3674)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                             at android.os.Looper.loop(Looper.java:154)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6128)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
    opened by icoolguy1995 4
  • Low res icons and trash_fix

    Low res icons and trash_fix



    As you can see, the drag icon isn't high res. I tried putting a high res pic there but it just appears big in size. Even the trash icons aren't displayed correctly. Can you direct me how to fix this ?

    opened by sanved77 4
  • Can't move view on some devices

    Can't move view on some devices

    I don't know why, My Pixel 3, Note 9 (Android Pie) works really well but view is not moving on some devices like Galaxy S8, Galaxy A8 2018 etc. Not also it can't be clicked but moving it. I already tested sample app on those devices but it was same.

    opened by HarryTylenol 3
  • NPE in addMovement

    NPE in addMovement

    We see in Crashlytics a rare exception on Samsung devices with Android 8 and 9:

    Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.VelocityTracker.addMovement(android.view.MotionEvent)' on a null object reference
           at jp.co.recruit_lifestyle.android.floatingview.FloatingView.addMovement + 927(FloatingView.java:927)
           at jp.co.recruit_lifestyle.android.floatingview.FloatingView.dispatchTouchEvent + 859(FloatingView.java:859)
           at android.view.View.dispatchPointerEvent + 13719(View.java:13719)
           at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent + 6111(ViewRootImpl.java:6111)
           at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess + 5889(ViewRootImpl.java:5889)
           at android.view.ViewRootImpl$InputStage.deliver + 5338(ViewRootImpl.java:5338)
           at android.view.ViewRootImpl$InputStage.onDeliverToNext + 5391(ViewRootImpl.java:5391)
           at android.view.ViewRootImpl$InputStage.forward + 5357(ViewRootImpl.java:5357)
           at android.view.ViewRootImpl$AsyncInputStage.forward + 5516(ViewRootImpl.java:5516)
           at android.view.ViewRootImpl$InputStage.apply + 5365(ViewRootImpl.java:5365)
           at android.view.ViewRootImpl$AsyncInputStage.apply + 5573(ViewRootImpl.java:5573)
           at android.view.ViewRootImpl$InputStage.deliver + 5338(ViewRootImpl.java:5338)
           at android.view.ViewRootImpl$InputStage.onDeliverToNext + 5391(ViewRootImpl.java:5391)
           at android.view.ViewRootImpl$InputStage.forward + 5357(ViewRootImpl.java:5357)
           at android.view.ViewRootImpl$InputStage.apply + 5365(ViewRootImpl.java:5365)
           at android.view.ViewRootImpl$InputStage.deliver + 5338(ViewRootImpl.java:5338)
           at android.view.ViewRootImpl.deliverInputEvent + 8400(ViewRootImpl.java:8400)
           at android.view.ViewRootImpl.doProcessInputEvents + 8333(ViewRootImpl.java:8333)
           at android.view.ViewRootImpl.enqueueInputEvent + 8286(ViewRootImpl.java:8286)
           at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent + 8515(ViewRootImpl.java:8515)
           at android.view.InputEventReceiver.dispatchInputEvent + 198(InputEventReceiver.java:198)
           at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(InputEventReceiver.java)
           at android.view.InputEventReceiver.consumeBatchedInputEvents + 187(InputEventReceiver.java:187)
           at android.view.ViewRootImpl.doConsumeBatchedInput + 8474(ViewRootImpl.java:8474)
           at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run + 8542(ViewRootImpl.java:8542)
           at android.view.Choreographer$CallbackRecord.run + 949(Choreographer.java:949)
           at android.view.Choreographer.doCallbacks + 761(Choreographer.java:761)
           at android.view.Choreographer.doFrame + 690(Choreographer.java:690)
           at android.view.Choreographer$FrameDisplayEventReceiver.run + 935(Choreographer.java:935)
           at android.os.Handler.handleCallback + 873(Handler.java:873)
           at android.os.Handler.dispatchMessage + 99(Handler.java:99)
           at android.os.Looper.loop + 214(Looper.java:214)
           at android.app.ActivityThread.main + 7058(ActivityThread.java:7058)
           at java.lang.reflect.Method.invoke(Method.java)
           at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 493(RuntimeInit.java:493)
           at com.android.internal.os.ZygoteInit.main + 965(ZygoteInit.java:965)
    opened by gmk57 1
  • get the removing view instead of coordinate

    get the removing view instead of coordinate

    nice job!

    i want to know which view was removed instead of the coordinate x&y in the onTouchFinished callback , this will make more sense. eg. i have list of floating views, and removed one, than i need to do some logic according to that view.

    opened by linisme 0
  • NullPointerException in onTouch, due to .getState()

    NullPointerException in onTouch, due to .getState()

    Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'int jp.co.recruit_lifestyle.android.floatingview.FloatingView.getState()' on a null object reference
           at jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager.onTouch(SourceFile:349)
           at com.geecko.QuickLyric.services.LyricsOverlayService.onTouch(SourceFile:969)
           at jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager.dispatchTouchEvent(SourceFile:906)

    This is the piece of code from FloatingViewManager.onTouch that triggers the exception:

            final int state = mTargetFloatingView.getState();
            mTargetFloatingView = (FloatingView) v;

    It seems like mTargetFloatingView can sometimes be null when the first line is executed.

    opened by geecko86 3
  • startObjectAnimation() only updates either X or Y

    startObjectAnimation() only updates either X or Y


    1. There should be a mMoveEdgeAnimatorX and a mMoveEdgeAnimatorY, not just one. Currently it only moves horizontally or vertically
    2. the moveTo() method should be public

    This is so that developers can move the floatingView themselves and do something like this:


    opened by geecko86 0
Recruit Lifestyle Co. Ltd.
Recruit Lifestyle Co. Ltd.
Recruit Lifestyle Co. Ltd.