[Guide] Creating a Floating Window out of your App

Search This thread

klinkdawg24

Senior Member
Nov 12, 2012
368
307
Iowa
This is a project that I whipped together to show developers how to implement a floating window type popup for their apps. An example usage would be quick reply to a sms message, email, or any other times quick reply would come in handy. It isn't limited to just that though, using this method, you will be able to completely recreate any activity in windowed form with very little code edits.

33m2xlh.png
2ug1bhd.png

My brother an I have used this to create a quick reply for our app, Sliding Messaging Pro. The idea is basically the exact same as Halo, with almost the exact same implementation. We do it by extending the MainActivity in a pop up class, then using an overrode setUpWindow() function to set up your MainActivity in the window.

The full source is availible on my GitHub, found here: Floating Window GitHub

Play Store Link: Floating Window Demo


So now to the actual steps to creating your own "floating window popup" out of your apps MainActivity:

1.) First, we should add the styles that we are going to use to the styles.xml sheet.

These are the styles for the animation, of course you can define your own animation if you choose, these will bring the window up from the bottom of the screen and the close it to the bottom of the screen.

Code:
    <style name="PopupAnimation" parent="@android:style/Animation">
        <item name="android:windowEnterAnimation">@anim/activity_slide_up</item>
        <item name="android:windowExitAnimation">@anim/activity_slide_down</item>
    </style>

Now, this style is for the actual popup dialog box. You can play with the different values here all you want. We end up overriding some of these when we set up the window anyways, such as the dimming.

Code:
    <style name="Theme.FloatingWindow.Popup" parent="@android:style/Theme.Holo.Light" >

        <item name="android:windowIsFloating">false</item>
        <item name="android:windowSoftInputMode">stateUnchanged</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowActionModeOverlay">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowAnimationStyle">@style/PopupAnimation</item>
        <item name="android:windowCloseOnTouchOutside">true</item>
        <item name="android:backgroundDimEnabled">false</item>

    </style>

2.) Now that your styles are set up, lets go ahead and add the new Popup activity to the manifest. You can see that we used the Theme.FloatingWindow.Popup style that we just defined in the last step. You will also have to add
Code:
xmlns:tools="http://schemas.android.com/tools"
to the xmlns declarations at the top of the manifest.

Code:
<activity
                android:name="PopupMainActivity"
                android:label="@string/app_name"
                android:theme="@style/Theme.FloatingWindow.Popup"
                android:configChanges="orientation|screenSize"
                android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
                android:clearTaskOnLaunch="true"
                android:exported="true"
                tools:ignore="ExportedActivity" />

3.) One more thing that we have to put in before you have resolved all the errors here, the animations. Just copy and paste these two animations in separate files under the res/anim folder. Name one activity_slide_down.xml and the other activity_slide_up.xml

activity_slide_down.xml
Code:
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate android:fromXDelta="0%" android:toXDelta="0%"
               android:fromYDelta="0%" android:toYDelta="100%"
               android:duration="300"/>

</set>

activity_slide_up.xml
Code:
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate android:fromXDelta="0%" android:toXDelta="0%"
               android:fromYDelta="100%" android:toYDelta="0%"
               android:duration="300"/>

</set>

4.) Now that everything should be set up, we will make the actual popup activity! You can view my full code for this from the GitHub link, but basically, we are going to make a PopupMainActivity.java class and extend the MainActivity class. If you understand inheritance at all with java, you will know what this is doing. It is going to allow this PopupMainActivity class, when started, to override methods from the MainActivity to produce different outcomes.

The method that actually makes the windowed pop up I have named setUpWindow(). This means that whenever this activity is called instead of the main activity, it will use this method instead of the main activities setUpWindow() method. This is very convieniet since we don't want to do any extra work than we need to in this class. So here is the code for that class:

Code:
/**
     * This method overrides the MainActivity method to set up the actual window for the popup.
     * This is really the only method needed to turn the app into popup form. Any other methods would change the behavior of the UI.
     * Call this method at the beginning of the main activity.
     * You can't call setContentView(...) before calling the window service because it will throw an error every time.
     */
    @Override
    public void setUpWindow() {

        // Creates the layout for the window and the look of it
        requestWindowFeature(Window.FEATURE_ACTION_BAR);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
                WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        // Params for the window.
        // You can easily set the alpha and the dim behind the window from here
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.alpha = 1.0f;    // lower than one makes it more transparent
        params.dimAmount = 0f;  // set it higher if you want to dim behind the window
        getWindow().setAttributes(params);

        // Gets the display size so that you can set the window to a percent of that
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int width = size.x;
        int height = size.y;

        // You could also easily used an integer value from the shared preferences to set the percent
        if (height > width) {
            getWindow().setLayout((int) (width * .9), (int) (height * .7));
        } else {
            getWindow().setLayout((int) (width * .7), (int) (height * .8));
        }
    }

You can see what it does from the comments, but basically, it just initializes your main activity in a windowed for, exactly what we are trying to do!

5.) Now to actually have this method override something in the MainActivity, you must add the same method there. In my example, The method is just blank and has no implementation because i don't want it to do anything extra for the full app. So add this activity and the error that "your method doesn't override anything in the super class" will go away. Then you actually have to call this method from your MainActivity's onCreate() method so that it will set up the windowed app when it is suppose to.

Code:
/**
     * Called when the activity is first created to set up all of the features.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        context = this;

        // If the user is in the PopupMainActivity function, the setUpWindow function would be called from that class
        // otherwise it would call the function from this class that has no implementation.
        setUpWindow();

        // Make sure to set your content view AFTER you have set up the window or it will crash.
        setContentView(R.layout.main);

        // Again, this will call either the function from this class or the PopupMainActivity one,
        // depending on where the user is
        setUpButton();
    }

As you can see from the code, I called this method before i set the content view for the activity. This is very important, otherwise you will get a runtime exception and the app will crash every time.



After you are done with that, you have successfully set up a program that will change from a windowed state to a full app state depending on which class is called. For example, if you set up an intent to open the floating window app, it would look something like this:

Code:
Intent window = new Intent(context, com.klinker.android.floating_window.PopupMainActivity.class);
window.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(window);

You are still able to call the MainActivity class like you normally would then. with an intent like this:

Code:
Intent fullApp = new Intent(context, MainActivity.class);
fullApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(fullApp);



That is just about it, obviously my solution and demo are very simple implementations of what it can do. You can see from the demo app that I simply go back and forth between the activities with a button, then i have an edittext at the bottom to demonstrate how the window resizes.

You can literally do anything with this though. It will work with any layouts you have set up and is a very cool way for your users to experience your app in a different light. If you want to change how something works in the popup part of the app, all you have to do is function that portion of code out, then override that method from the popup activity, so the possibilities are endless with what can be done here.

Credit for this goes to the Paranoid Android team of course for inspiring the idea, then Jacob Klinker (klinkdawg) and myself (Luke Klinker) for the implementation without framework tweaks or custom roms. This should work for any users, no matter the phone, android version, or custom rom.

I honestly have no clue if it will work on anything below 4.0, but if you test and find out, sound off in the comments!

Thanks and enjoy! I hope to see lots of dynamic and awesome popups in the future because it really is just that simple, it won't take you more than a half hour to get this working! :)
 
Last edited:

bendrum30

Senior Member
Aug 18, 2010
97
15
Samsung Galaxy S21 Ultra
I love your Sliding Messaging app. Really awesome work. The BEST messaging app out there. I'm in the beta group. Thank you for this information!

Sent from my XT875 using Tapatalk
 

xela92

Senior Member
Aug 7, 2009
152
111
Thank you for your sharing.
I used your example to add this amazing feature into Telepatch, an Open Source project, fork of Telegram :)

Thanks again!
 

yousefs

Senior Member
Jan 12, 2014
103
12
plus.google.com
[Idea] Create FloatingActivity type

This is an extremely awesome project, easy to implement, and very light weight, however, the only problem is that when i call the floating activity for example from a notification or whatever, the background activity closes, and i haven't been able to get around it

However, just an idea, which is what i did, create a separate Activity and put the setUpWindow() method in it, and override the onCreate() method and setUpWindow() in it, and after that, you can just create any activity and extends the FloatingActivity class and you're done, just make sure that you call super.onCreate() if you (probably) overrided the onCreate() method:laugh:
 

burakgon

Senior Member
Oct 26, 2010
3,054
3,799
www.burakgon.com
Hi, I've tried your solution. It works perfectly!

But when we touch homescreen button, the app is minimized. How can we make it persistent?
 

Top Liked Posts

  • There are no posts matching your filters.
  • 11
    This is a project that I whipped together to show developers how to implement a floating window type popup for their apps. An example usage would be quick reply to a sms message, email, or any other times quick reply would come in handy. It isn't limited to just that though, using this method, you will be able to completely recreate any activity in windowed form with very little code edits.

    33m2xlh.png
    2ug1bhd.png

    My brother an I have used this to create a quick reply for our app, Sliding Messaging Pro. The idea is basically the exact same as Halo, with almost the exact same implementation. We do it by extending the MainActivity in a pop up class, then using an overrode setUpWindow() function to set up your MainActivity in the window.

    The full source is availible on my GitHub, found here: Floating Window GitHub

    Play Store Link: Floating Window Demo


    So now to the actual steps to creating your own "floating window popup" out of your apps MainActivity:

    1.) First, we should add the styles that we are going to use to the styles.xml sheet.

    These are the styles for the animation, of course you can define your own animation if you choose, these will bring the window up from the bottom of the screen and the close it to the bottom of the screen.

    Code:
        <style name="PopupAnimation" parent="@android:style/Animation">
            <item name="android:windowEnterAnimation">@anim/activity_slide_up</item>
            <item name="android:windowExitAnimation">@anim/activity_slide_down</item>
        </style>

    Now, this style is for the actual popup dialog box. You can play with the different values here all you want. We end up overriding some of these when we set up the window anyways, such as the dimming.

    Code:
        <style name="Theme.FloatingWindow.Popup" parent="@android:style/Theme.Holo.Light" >
    
            <item name="android:windowIsFloating">false</item>
            <item name="android:windowSoftInputMode">stateUnchanged</item>
            <item name="android:windowContentOverlay">@null</item>
            <item name="android:windowActionModeOverlay">true</item>
            <item name="android:windowIsTranslucent">true</item>
            <item name="android:windowFrame">@null</item>
            <item name="android:windowAnimationStyle">@style/PopupAnimation</item>
            <item name="android:windowCloseOnTouchOutside">true</item>
            <item name="android:backgroundDimEnabled">false</item>
    
        </style>

    2.) Now that your styles are set up, lets go ahead and add the new Popup activity to the manifest. You can see that we used the Theme.FloatingWindow.Popup style that we just defined in the last step. You will also have to add
    Code:
    xmlns:tools="http://schemas.android.com/tools"
    to the xmlns declarations at the top of the manifest.

    Code:
    <activity
                    android:name="PopupMainActivity"
                    android:label="@string/app_name"
                    android:theme="@style/Theme.FloatingWindow.Popup"
                    android:configChanges="orientation|screenSize"
                    android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
                    android:clearTaskOnLaunch="true"
                    android:exported="true"
                    tools:ignore="ExportedActivity" />

    3.) One more thing that we have to put in before you have resolved all the errors here, the animations. Just copy and paste these two animations in separate files under the res/anim folder. Name one activity_slide_down.xml and the other activity_slide_up.xml

    activity_slide_down.xml
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    
    <set xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <translate android:fromXDelta="0%" android:toXDelta="0%"
                   android:fromYDelta="0%" android:toYDelta="100%"
                   android:duration="300"/>
    
    </set>

    activity_slide_up.xml
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    
    <set xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <translate android:fromXDelta="0%" android:toXDelta="0%"
                   android:fromYDelta="100%" android:toYDelta="0%"
                   android:duration="300"/>
    
    </set>

    4.) Now that everything should be set up, we will make the actual popup activity! You can view my full code for this from the GitHub link, but basically, we are going to make a PopupMainActivity.java class and extend the MainActivity class. If you understand inheritance at all with java, you will know what this is doing. It is going to allow this PopupMainActivity class, when started, to override methods from the MainActivity to produce different outcomes.

    The method that actually makes the windowed pop up I have named setUpWindow(). This means that whenever this activity is called instead of the main activity, it will use this method instead of the main activities setUpWindow() method. This is very convieniet since we don't want to do any extra work than we need to in this class. So here is the code for that class:

    Code:
    /**
         * This method overrides the MainActivity method to set up the actual window for the popup.
         * This is really the only method needed to turn the app into popup form. Any other methods would change the behavior of the UI.
         * Call this method at the beginning of the main activity.
         * You can't call setContentView(...) before calling the window service because it will throw an error every time.
         */
        @Override
        public void setUpWindow() {
    
            // Creates the layout for the window and the look of it
            requestWindowFeature(Window.FEATURE_ACTION_BAR);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
                    WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    
            // Params for the window.
            // You can easily set the alpha and the dim behind the window from here
            WindowManager.LayoutParams params = getWindow().getAttributes();
            params.alpha = 1.0f;    // lower than one makes it more transparent
            params.dimAmount = 0f;  // set it higher if you want to dim behind the window
            getWindow().setAttributes(params);
    
            // Gets the display size so that you can set the window to a percent of that
            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            int width = size.x;
            int height = size.y;
    
            // You could also easily used an integer value from the shared preferences to set the percent
            if (height > width) {
                getWindow().setLayout((int) (width * .9), (int) (height * .7));
            } else {
                getWindow().setLayout((int) (width * .7), (int) (height * .8));
            }
        }

    You can see what it does from the comments, but basically, it just initializes your main activity in a windowed for, exactly what we are trying to do!

    5.) Now to actually have this method override something in the MainActivity, you must add the same method there. In my example, The method is just blank and has no implementation because i don't want it to do anything extra for the full app. So add this activity and the error that "your method doesn't override anything in the super class" will go away. Then you actually have to call this method from your MainActivity's onCreate() method so that it will set up the windowed app when it is suppose to.

    Code:
    /**
         * Called when the activity is first created to set up all of the features.
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            context = this;
    
            // If the user is in the PopupMainActivity function, the setUpWindow function would be called from that class
            // otherwise it would call the function from this class that has no implementation.
            setUpWindow();
    
            // Make sure to set your content view AFTER you have set up the window or it will crash.
            setContentView(R.layout.main);
    
            // Again, this will call either the function from this class or the PopupMainActivity one,
            // depending on where the user is
            setUpButton();
        }

    As you can see from the code, I called this method before i set the content view for the activity. This is very important, otherwise you will get a runtime exception and the app will crash every time.



    After you are done with that, you have successfully set up a program that will change from a windowed state to a full app state depending on which class is called. For example, if you set up an intent to open the floating window app, it would look something like this:

    Code:
    Intent window = new Intent(context, com.klinker.android.floating_window.PopupMainActivity.class);
    window.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(window);

    You are still able to call the MainActivity class like you normally would then. with an intent like this:

    Code:
    Intent fullApp = new Intent(context, MainActivity.class);
    fullApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(fullApp);



    That is just about it, obviously my solution and demo are very simple implementations of what it can do. You can see from the demo app that I simply go back and forth between the activities with a button, then i have an edittext at the bottom to demonstrate how the window resizes.

    You can literally do anything with this though. It will work with any layouts you have set up and is a very cool way for your users to experience your app in a different light. If you want to change how something works in the popup part of the app, all you have to do is function that portion of code out, then override that method from the popup activity, so the possibilities are endless with what can be done here.

    Credit for this goes to the Paranoid Android team of course for inspiring the idea, then Jacob Klinker (klinkdawg) and myself (Luke Klinker) for the implementation without framework tweaks or custom roms. This should work for any users, no matter the phone, android version, or custom rom.

    I honestly have no clue if it will work on anything below 4.0, but if you test and find out, sound off in the comments!

    Thanks and enjoy! I hope to see lots of dynamic and awesome popups in the future because it really is just that simple, it won't take you more than a half hour to get this working! :)