Floating widgets float over the screen over any app that is currently running.

Here we will make a floating action button that you can drag around the screen to position and do actions on it.


Add Permission

For drawing over the other apps, you need “android.permission.SYSTEM_ALERT_WINDOW” permission.

So add this entry in your manifest.

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

Our Manifest will look like this

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="floating_demo.coderzheaven.com.floatingdemo">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".FloatingService"
            android:enabled="true"
            android:exported="false" />
    </application>

</manifest>

Layout

<?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"
    tools:context="floating_demo.coderzheaven.com.floatingdemo.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="Floating action Demo\n(coderzheaven.com)" />

    <Button
        android:id="@+id/createBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create Floating Button"
        android:layout_centerInParent="true"
        android:textColor="@android:color/white"
        android:layout_marginBottom="30dp"
        android:padding="10dp"
        android:background="@color/colorAccent"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>

The next layout is shown when the floating button is clicked.
We will name it floating_layout.xml.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/parentRel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:id="@+id/r1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/mainButton"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_alignParentTop="true"
                android:src="@mipmap/ic_launcher" />

            <ImageView
                android:id="@+id/closeBtn"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginLeft="30dp"
                android:src="@android:drawable/ic_dialog_info" />

        </RelativeLayout>

        <LinearLayout
            android:id="@+id/showLin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_toRightOf="@+id/r1"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:padding="20dp"
            android:visibility="gone">

            <ImageView
                android:id="@+id/btnInfo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@android:drawable/ic_dialog_info" />

        </LinearLayout>
    </RelativeLayout>
</FrameLayout>

Activity and the Floating Service

MainActivity

package floating_demo.coderzheaven.com.floatingdemo;

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

public class MainActivity extends AppCompatActivity {

    private static final int APP_OVERLAY_PERMISSION = 1000;
    private Context context;

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

        context = this;

        // Asking for permission from user...
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, APP_OVERLAY_PERMISSION);
        }

        findViewById(R.id.createBtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context))) {
                    // Permission was already granted..starting service for creating the Floating Button UI...
                    startService(new Intent(context, FloatingService.class));
                    finish();
                }
            }
        });

        findViewById(R.id.createBtn).setVisibility(checkIfOverlayPermissionGranted() ? View.VISIBLE : View.GONE);
    }

    Boolean checkIfOverlayPermissionGranted() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(context);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context))) {
            // Permission was already granted..starting service for creating the Floating Button UI...
            startService(new Intent(context, FloatingService.class));
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == APP_OVERLAY_PERMISSION) {
            showMessage(checkIfOverlayPermissionGranted() ? "Overlay Permission Granted :)" : "Overlay Permission Denied :(");
            findViewById(R.id.createBtn).setVisibility(checkIfOverlayPermissionGranted() ? View.VISIBLE : View.GONE);
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    // Shows message to the user...
    void showMessage(String message) {
        Toast.makeText(context, message, Toast.LENGTH_LONG).show();
    }

}

We will use a service to draw the floating button over other apps.
Create a java file named FloatingService.java which extends Service.

package floating_demo.coderzheaven.com.floatingdemo;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

public class FloatingService extends Service implements OnClickListener, View.OnTouchListener {

    private WindowManager mWindowManager;
    private View mFloatingView;
    private ImageView mainButton;
    private LinearLayout showLin;
    private ImageView btnInfo;
    private WindowManager.LayoutParams params;
    private ImageView btnClose;
    int initialX = 0;
    int initialY = 0;
    float initialTouchX = 0;
    float initialTouchY = 0;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //Inflate the floating view layout we created
        mFloatingView = LayoutInflater.from(this).inflate(R.layout.floating_layout, null);

        //Add the view to the window.
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        // Set the position to the top right corner of the screen
        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 50;
        params.y = 50;

        //Add the view to the window
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        mWindowManager.addView(mFloatingView, params);

        mainButton = (ImageView) mFloatingView.findViewById(R.id.mainButton);
        btnClose = (ImageView) mFloatingView.findViewById(R.id.closeBtn);
        btnInfo = (ImageView) mFloatingView.findViewById(R.id.btnInfo);
        showLin = (LinearLayout) mFloatingView.findViewById(R.id.showLin);

        mainButton.setOnClickListener(this);
        btnInfo.setOnClickListener(this);
        btnClose.setOnClickListener(this);

        //Drag and move floating view using user's touch action.
        mainButton.setOnTouchListener(this);
    }

    @Override
    public void onClick(View view) {
        if (view == btnClose) {
            int vis = (showLin.getVisibility() == View.VISIBLE) ? View.GONE : View.VISIBLE;
            showLin.setVisibility(vis);
        }
        if (view == btnInfo) {
            Intent intent = new Intent(FloatingService.this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

            // Stop the service and Remove the Floating Button when our app opens...
            stopSelf();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (null != mFloatingView && null != mWindowManager)
            mWindowManager.removeView(mFloatingView);
    }

    // Shows message to the user...
    void showMessage(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {

        showLin.setVisibility(View.GONE);

        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:

                //remember the initial position.
                //initialX = params.x;
                //initialY = params.y;

                //get the touch location
                initialTouchX = motionEvent.getRawX();
                initialTouchY = motionEvent.getRawY();
                return true;
            case MotionEvent.ACTION_UP:
                return true;
            case MotionEvent.ACTION_MOVE:
                //Calculate the X and Y coordinates of the view.
                params.x = (int) (motionEvent.getRawX() - initialTouchX) - initialX;
                params.y = (int) (motionEvent.getRawY() - initialTouchY) - initialY;

                //Update the layout with new X & Y coordinate
                mWindowManager.updateViewLayout(mFloatingView, params);
                return true;
        }
        return false;
    }

}


Source Code

You can download the complete source code from here.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

 

 

 

Theme by HermesThemes

Copyright © 2018 CoderzHeaven. All Rights Reserved

Please wait...

Subscribe to our newsletter

Want to be notified when our article is published? Enter your email address and name below to be the first to know.