Suspension Windows are a common requirement. For example, the video call screen can be reduced to a floating window, so that users can do things on other screens.

This paper presents a simple implementation of suspension window. You can reduce the activity and restore the size. Can be suspended over other activities. Use TouchListener to listen for touch events and drag the hover window.

This article links

Scaling method

Scaling the activity needs to use WindowManager. LayoutParams, high control window width

Called in the activity

android.view.WindowManager.LayoutParams p = getWindow().getAttributes();
p.height = 480; / / height
p.width = 360;  / / width
p.dimAmount = 0.0 f; // Do not darken the interface below
getWindow().setAttributes(p);
Copy the code

Dim; Dim; A faint; Not bright; Dimly lit; Dim, dim, dim, dim (cause) to become dull or tarnished;

Modified the WindowManager. LayoutParams width is high, the activity of the window size changes.

To return to the default size, call it in the activity

getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
Copy the code

If you change position while zooming out, you need to set the window position to 0

WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.x = 0;
lp.y = 0;
getWindow().setAttributes(lp);
Copy the code

The activity becomes small and may have a black background behind it. This requires the following operation.

Suspension style

Create a new MeTranslucentAct in styles. XML.

<resources>
    <! -- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <! -- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="TranslucentAct" parent="AppTheme">
        <item name="android:windowBackground"># 80000000</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
    </style>
</resources>
Copy the code

The main style is AppCompat.

Specifies a window background android: windowBackground use Activity inherited from androidx. Appcompat. App. AppCompatActivity

When the activity zooms out, the background is transparent and you can see the rest of the page behind it

Click through white space

When the activity is zoomed out and clicked in the space next to it, other components receive click events

The setContentView before onCreate method, give a WindowManager. Add mark FLAG_LAYOUT_NO_LIMITS and FLAG_NOT_TOUCH_MODAL LayoutParams

WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); layoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;  mBinding = DataBindingUtil.setContentView(this, R.layout.act_float_scale);
Copy the code

Floating window

Listen for touch events, calculate how far your finger moves, and then move the suspension window.

private boolean mIsSmall = false; // Whether the current window is small
private float mLastTx = 0; // The upper position of the finger is x
private float mLastTy = 0;
/ /...

    mBinding.root.setOnTouchListener((v, event) -> {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "down " + event);
                mLastTx = event.getRawX();
                mLastTy = event.getRawY();
                return true;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "move " + event);
                float dx = event.getRawX() - mLastTx;
                float dy = event.getRawY() - mLastTy;
                mLastTx = event.getRawX();
                mLastTy = event.getRawY();
                Log.d(TAG, " dx: " + dx + ", dy: " + dy);
                if (mIsSmall) {
                    WindowManager.LayoutParams lp = getWindow().getAttributes();
                    lp.x += dx;
                    lp.y += dy;
                    getWindow().setAttributes(lp);
                }

                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "up " + event);
                return true;
            case MotionEvent.ACTION_CANCEL:
                Log.d(TAG, "cancel " + event);
                return true;
        }
        return false;
    });
Copy the code

MIsSmall is used to record whether the current activity is small (floating).

Return true in the touch listener to consume the touch event.

Event.getx () and event.gety () get the touch coordinates of the current View. Event.getrawx () and event.getrawy () get the touch coordinates of the screen. That’s where the touch point is on the screen.

The complete code for the example

To enable the databinding

android {
    dataBinding {
        enabled = true}}Copy the code

styles.xml

Create a new style

    <style name="TranslucentAct" parent="AppTheme">
        <item name="android:windowBackground"># 80000000</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
    </style>
Copy the code

layout

Act_float_scale.xml has some buttons inside it that zoom in and out. ConstraintLayout listens for touch events.


      
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="# 555555">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical"
            app:layout_constraintTop_toTopOf="parent">

            <Button
                android:id="@+id/to_small"
                style="@style/NormalBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Smaller" />

            <Button
                android:id="@+id/to_reset"
                style="@style/NormalBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="12dp"
                android:text="Reduction" />
        </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Copy the code

activity

FloatingScaleAct

import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import com.rustfisher.tutorial2020.R;
import com.rustfisher.tutorial2020.databinding.ActFloatScaleBinding;

public class FloatingScaleAct extends AppCompatActivity {
    private static final String TAG = "rfDevFloatingAct";

    ActFloatScaleBinding mBinding;

    private boolean mIsSmall = false; // Whether the current window is small
    private float mLastTx = 0; // The upper position of the finger
    private float mLastTy = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); layoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;  mBinding = DataBindingUtil.setContentView(this, R.layout.act_float_scale);

        mBinding.toSmall.setOnClickListener(v -> toSmall());
        mBinding.toReset.setOnClickListener(v -> {
            WindowManager.LayoutParams lp = getWindow().getAttributes();
            lp.x = 0;
            lp.y = 0;
            getWindow().setAttributes(lp);
            getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            mIsSmall = false;
        });

        mBinding.root.setOnTouchListener((v, event) -> {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.d(TAG, "down " + event);
                    mLastTx = event.getRawX();
                    mLastTy = event.getRawY();
                    return true;
                case MotionEvent.ACTION_MOVE:
                    Log.d(TAG, "move " + event);
                    float dx = event.getRawX() - mLastTx;
                    float dy = event.getRawY() - mLastTy;
                    mLastTx = event.getRawX();
                    mLastTy = event.getRawY();
                    Log.d(TAG, " dx: " + dx + ", dy: " + dy);
                    if (mIsSmall) {
                        WindowManager.LayoutParams lp = getWindow().getAttributes();
                        lp.x += dx;
                        lp.y += dy;
                        getWindow().setAttributes(lp);
                    }

                    break;
                case MotionEvent.ACTION_UP:
                    Log.d(TAG, "up " + event);
                    return true;
                case MotionEvent.ACTION_CANCEL:
                    Log.d(TAG, "cancel " + event);
                    return true;
            }
            return false;
        });
    }

    private void toSmall(a) {
        mIsSmall = true;

        WindowManager m = getWindowManager();
        Display d = m.getDefaultDisplay();
        WindowManager.LayoutParams p = getWindow().getAttributes();
        p.height = (int) (d.getHeight() * 0.35);
        p.width = (int) (d.getWidth() * 0.4);
        p.dimAmount = 0.0 f; getWindow().setAttributes(p); }}Copy the code

Register the activity in the manifest

<activity
    android:name=".act.FloatingScaleAct"
    android:theme="@style/TranslucentAct" />
Copy the code

Running effect

Run OK on Redmi 9A (Android 10, MIUI 12.5.1 Stable) and Glory (Android 5.1)

summary

To achieve the floating window effect, the idea is to change the size of the activity, make the background of the window where the activity is located transparent, and listen for touch events to change the position of the window. The main classes used WindowManager. LayoutParams

This article links