How to Create Android Floating Widget To Let Multiple Views Float

Do you want to create an Android floating widget for your app? No need to look here and there. Through this post, we will take you through the process of creating a floating widget in Android. Stay tuned until the end, and you will be able to create a floating widget for your application.

Floating widgets are the views that generally float over the device screen. This Android floating view will remain floating no matter whatever screen you are in. The floating widget in Android basically helps in multitasking as a user can work on other apps and control your app as well.

For instance, if the user is using a calculator and your app is a music player, the user can still use your app through floating layout Android while using the calculator at the same time.

In this Android layout height wrap app development tutorial, we will see the implementation process of the Android floating widget in an Android app.

Looking for an Android App Developers?

Get in touch with us. We have experienced Android app developers who develops custom app solution tailored to your

Cta Image

Steps to Create Android Floating Widget

  • First of all, open your Android Studio and create a new project.
  • In the next tab, select your target Android device.
  • Select ‘Empty Activity’ and click on next.
  • Lastly, customize the activity.
  • Create Java class name “FloatWidgetService”

package com.floatingwidget;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

public class FloatWidgetService extends Service {
    private WindowManager mWindowManager;
    private View mFloatingWidget;
    public FloatWidgetService() {
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        mFloatingWidget = LayoutInflater.from(this).inflate(R.layout.layout_floating_widget, null);
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT
        );
        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 100;
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mFloatingWidget, params);

        final View collapsedView = mFloatingWidget.findViewById(R.id.collapse_view);
        final View expandedView = mFloatingWidget.findViewById(R.id.expanded_container);
        ImageView closeButtonCollapsed = (ImageView) mFloatingWidget.findViewById(R.id.close_btn);
        closeButtonCollapsed.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopSelf();
            }
        });
        ImageView closeButton = (ImageView) mFloatingWidget.findViewById(R.id.close_button);
        closeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                collapsedView.setVisibility(View.VISIBLE);
                expandedView.setVisibility(View.GONE);
            }
        });
        mFloatingWidget.findViewById(R.id.root_container).setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        initialX = params.x;
                        initialY = params.y;
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();
                        return true;
                    case MotionEvent.ACTION_UP:
                        int Xdiff = (int) (event.getRawX() - initialTouchX);
                        int Ydiff = (int) (event.getRawY() - initialTouchY);
                        if (Xdiff < 10 && Ydiff < 10) {
                            if (isViewCollapsed()) {
                                collapsedView.setVisibility(View.GONE);
                                expandedView.setVisibility(View.VISIBLE);
                            }
                        }
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        params.x = initialX + (int) (event.getRawX() - initialTouchX);
                        params.y = initialY + (int) (event.getRawY() - initialTouchY);
                        mWindowManager.updateViewLayout(mFloatingWidget, params);
                        return true;
                }
                return false;
            }
		});
	}
            private boolean isViewCollapsed() {
                return mFloatingWidget == null || mFloatingWidget.findViewById(R.id.collapse_view).getVisibility() == View.VISIBLE;
             }
            @Override
            public void onDestroy() {
                super.onDestroy();
                if (mFloatingWidget != null) mWindowManager.removeView(mFloatingWidget);
	}
}
Copy to Clipboard

hand icon Add Permission in Manifest

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Copy to Clipboard

hand icon Add Service in Manifest

<service
android:name=".FloatWidgetService"
android:enabled="true"
android:exported="false"/>
Copy to Clipboard

hand icon MainActivity

package com.floatingwidget;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
	private static final int APP_PERMISSION_REQUEST = 102;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
			Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
					Uri.parse("package:" + getPackageName()));
			startActivityForResult(intent, APP_PERMISSION_REQUEST);
		} else {
			initializeView();
		}
	}

	private void initializeView() {
		Button mButton = (Button) findViewById(R.id.createBtn);
		mButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				startService(new Intent(MainActivity.this, FloatWidgetService.class));
				finish();
			}
		});
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == APP_PERMISSION_REQUEST && resultCode == RESULT_OK) {
			initializeView();
		} else {
			Toast.makeText(this, "Draw over other app permission not enabled.", Toast.LENGTH_SHORT).show();
		}
	}
}
Copy to Clipboard

hand icon activity_main.xml

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout
    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">

    <Button
        android:id="@+id/createBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:backgroundTint="#00C1E7"
        android:text="Setup Floating Widget"
        android:textColor="@android:color/white" />
</RelativeLayout>
Copy to Clipboard

hand icon layout_floating_widget.xml

<?xml version="1.0" encoding="utf-8"?>  
  <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
    <RelativeLayout
          android:id="@+id/root_container"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          tools:ignore="UselessParent">
        <RelativeLayout
            android:id="@+id/collapse_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:visibility="visible">
          <ImageView
              android:id="@+id/collapsed_iv"
              android:layout_width="70dp"
              android:layout_height="70dp"
              android:layout_marginTop="8dp"
              android:src="@drawable/diamond"
              tools:ignore="ContentDescription" />
          <ImageView
              android:id="@+id/close_btn"
              android:layout_width="25dp"
              android:layout_height="25dp"
              android:layout_marginLeft="50dp"
              android:src="@drawable/error"
              tools:ignore="ContentDescription" />
        </RelativeLayout>
        <LinearLayout
            android:visibility="gone"
            android:id="@+id/expanded_container"
            android:layout_width="wrap_content"
            android:layout_height="80dp"
            android:background="#00C1E7"
            android:orientation="horizontal"
            android:padding="5dp">
          <ImageView
            android:layout_width= "70dp"
            android:layout_height= "70dp"
            android:src= "@drawable/diamond"
            tools:ignore= "ContentDescription" />
          <TextView
              android:lineSpacingExtra="1dp"
              android:layout_width="100dp"
              android:layout_height="match_parent"
              android:gravity="center_vertical"
              android:padding="5dp"
              android:text="Floating Widget contols here"
              android:textColor="@android:color/white"
              android:textSize="14sp"
              android:textStyle="bold" />
          <TextView
              android:id="@+id/close_button"
              android:layout_width="25dp"
              android:layout_height="25dp"
              android:src="@drawable/error"
              tools:ignore="ContentDescription" />
        </LinearLayout>
      </RelativeLayout>
  </FrameLayout>
Copy to Clipboard

That’s It!

Although, if you face any issue, or implementing floating widget Android in your startup app development, considering advice from an expert and Android app development company is better for your app as well as your startup. Here, we have listed a few of the most common questions we receive on a daily basis.

Grab a free copy of Floating Android Widget Tutorial from Github.

Frequently Asked Questions

Where are floating widgets used in Android?

One of the most popular use-cases of floating widgets is Facebook’s chat head bubble button. Apart from that, apps like Uber and Ola also have floating widgets that help drivers switch from the app to maps and vice versa.

What are the benefits of Android floating widgets?

Android floating widgets make multi-tasking easy and seamless. They allow users to toggle between two apps swiftly and with just a single tap.

Can I create Android floating widgets/buttons in iOS?

Yes. You can create it by creating your own subclass of UIWindow, and then creating an instance of that subclass. For more information, you can follow this thread.

Conclusion

We hope this tutorial helped you create an Android floating widget for your app. Being an Android app development company, we have been working with Android for a decade now. Thus, if you are nurturing an idea for creating your own app or seeking guidance — feel free to get in touch with us. We will be happy to help.

Bhaval Patel

Written by

Bhaval Patel is a Director (Operations) at Space-O Technologies. He has 20+ years of experience helping startups and enterprises with custom software solutions to drive maximum results. Under his leadership, Space-O has won the 8th GESIA annual award for being the best mobile app development company. So far, he has validated more than 300 app ideas and successfully delivered 100 custom solutions using the technologies, such as Swift, Kotlin, React Native, Flutter, PHP, RoR, IoT, AI, NFC, AR/VR, Blockchain, NFT, and more.