Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
String overlayContent = call.argument("overlayContent");
String notificationVisibility = call.argument("notificationVisibility");
boolean enableDrag = call.argument("enableDrag");
boolean enableBounce = call.argument("enableBounce");
int bounceHeight = call.argument("bounceHeight");
int bounceDuration = call.argument("bounceDuration");
String positionGravity = call.argument("positionGravity");
Map<String, Integer> startPosition = call.argument("startPosition");
int startX = startPosition != null ? startPosition.getOrDefault("x", OverlayConstants.DEFAULT_XY) : OverlayConstants.DEFAULT_XY;
Expand All @@ -95,6 +98,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
WindowSetup.width = width != null ? width : -1;
WindowSetup.height = height != null ? height : -1;
WindowSetup.enableDrag = enableDrag;
WindowSetup.enableBounce = enableBounce;
WindowSetup.bounceHeight = bounceHeight;
WindowSetup.bounceDuration = bounceDuration;
WindowSetup.setGravityFromAlignment(alignment != null ? alignment : "center");
WindowSetup.setFlag(flag != null ? flag : "flagNotFocusable");
WindowSetup.overlayTitle = overlayTitle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
Expand Down Expand Up @@ -71,6 +74,9 @@ public class OverlayService extends Service implements View.OnTouchListener {
private Point szWindow = new Point();
private Timer mTrayAnimationTimer;
private TrayAnimationTimerTask mTrayTimerTask;
private int bounceBaseY = 0; // px
private int bounceAmplitudePx = 0; // px
private ObjectAnimator bounceAnimator;

@Nullable
@Override
Expand All @@ -82,6 +88,8 @@ public IBinder onBind(Intent intent) {
@Override
public void onDestroy() {
Log.d("OverLay", "Destroying the overlay window service");
stopBounce();
stopTrayAnimation();
if (windowManager != null) {
windowManager.removeView(flutterView);
windowManager = null;
Expand All @@ -102,6 +110,8 @@ public int onStartCommand(Intent intent, int flags, int startId) {
int startY = intent.getIntExtra("startY", OverlayConstants.DEFAULT_XY);
boolean isCloseWindow = intent.getBooleanExtra(INTENT_EXTRA_IS_CLOSE_WINDOW, false);
if (isCloseWindow) {
stopBounce();
stopTrayAnimation();
if (windowManager != null) {
windowManager.removeView(flutterView);
windowManager = null;
Expand All @@ -112,6 +122,8 @@ public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
if (windowManager != null) {
stopBounce();
stopTrayAnimation();
windowManager.removeView(flutterView);
windowManager = null;
flutterView.detachFromFlutterEngine();
Expand Down Expand Up @@ -139,7 +151,10 @@ public int onStartCommand(Intent intent, int flags, int startId) {
int width = call.argument("width");
int height = call.argument("height");
boolean enableDrag = call.argument("enableDrag");
resizeOverlay(width, height, enableDrag, result);
boolean enableBounce = call.argument("enableBounce");
int bounceHeight = call.argument("bounceHeight");
int bounceDuration = call.argument("bounceDuration");
resizeOverlay(width, height, enableDrag, enableBounce, bounceHeight, bounceDuration, result);
}
});
overlayMessageChannel.setMessageHandler((message, reply) -> {
Expand Down Expand Up @@ -177,6 +192,12 @@ public int onStartCommand(Intent intent, int flags, int startId) {
flutterView.setOnTouchListener(this);
windowManager.addView(flutterView, params);
moveOverlay(dx, dy, null);
if (WindowSetup.enableBounce) {
WindowManager.LayoutParams p = (WindowManager.LayoutParams) flutterView.getLayoutParams();
bounceBaseY = p.y;
bounceAmplitudePx = dpToPx(WindowSetup.bounceHeight);
startBounce();
}
return START_STICKY;
}

Expand Down Expand Up @@ -240,13 +261,22 @@ private void updateOverlayFlag(MethodChannel.Result result, String flag) {
}
}

private void resizeOverlay(int width, int height, boolean enableDrag, MethodChannel.Result result) {
private void resizeOverlay(int width, int height, boolean enableDrag, boolean enableBounce, int bounceHeight, int bounceDuration, MethodChannel.Result result) {
if (windowManager != null) {
WindowManager.LayoutParams params = (WindowManager.LayoutParams) flutterView.getLayoutParams();
params.width = (width == -1999 || width == -1) ? -1 : dpToPx(width);
params.height = (height != 1999 || height != -1) ? dpToPx(height) : height;
WindowSetup.enableDrag = enableDrag;
WindowSetup.enableBounce = enableBounce;
WindowSetup.bounceHeight = bounceHeight;
WindowSetup.bounceDuration = bounceDuration;
windowManager.updateViewLayout(flutterView, params);
if (WindowSetup.enableBounce) {
bounceAmplitudePx = dpToPx(WindowSetup.bounceHeight);
startBounce();
} else {
stopBounce();
}
result.success(true);
} else {
result.success(false);
Expand Down Expand Up @@ -380,6 +410,7 @@ public boolean onTouch(View view, MotionEvent event) {
WindowManager.LayoutParams params = (WindowManager.LayoutParams) flutterView.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
stopBounce();
dragging = false;
lastX = event.getRawX();
lastY = event.getRawY();
Expand Down Expand Up @@ -417,6 +448,11 @@ public boolean onTouch(View view, MotionEvent event) {
mTrayAnimationTimer = new Timer();
mTrayAnimationTimer.schedule(mTrayTimerTask, 0, 25);
}
if (WindowSetup.enableBounce) {
// reset base to current position and resume bounce
bounceBaseY = params.y;
startBounce();
}
return false;
default:
return false;
Expand Down Expand Up @@ -467,5 +503,42 @@ public void run() {
}
}

private void startBounce() {
stopBounce();
if (flutterView == null) return;
if (bounceAmplitudePx <= 0) bounceAmplitudePx = dpToPx(WindowSetup.bounceHeight);
float from = -bounceAmplitudePx;
float to = bounceAmplitudePx;
bounceAnimator = ObjectAnimator.ofFloat(flutterView, View.TRANSLATION_Y, from, to);
// Interpret bounceDuration as duration per full cycle (ms)
int duration = WindowSetup.bounceDuration <= 50 ? WindowSetup.bounceDuration * 100 : WindowSetup.bounceDuration;
duration = Math.max(300, duration);
bounceAnimator.setDuration(duration);
bounceAnimator.setRepeatMode(ValueAnimator.REVERSE);
bounceAnimator.setRepeatCount(ValueAnimator.INFINITE);
bounceAnimator.setInterpolator(new LinearInterpolator());
bounceAnimator.start();
}

private void stopBounce() {
if (bounceAnimator != null) {
bounceAnimator.cancel();
bounceAnimator = null;
}
if (flutterView != null) {
flutterView.clearAnimation();
flutterView.setTranslationY(0f);
}
}

private void stopTrayAnimation() {
if (mTrayTimerTask != null) {
mTrayTimerTask.cancel();
mTrayTimerTask = null;
}
if (mTrayAnimationTimer != null) {
mTrayAnimationTimer.cancel();
mTrayAnimationTimer = null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package flutter.overlay.window.flutter_overlay_window;


import android.view.Gravity;
import android.view.WindowManager;

Expand All @@ -20,7 +19,9 @@ public abstract class WindowSetup {
static String positionGravity = "none";
static int notificationVisibility = NotificationCompat.VISIBILITY_PRIVATE;
static boolean enableDrag = false;

static boolean enableBounce = false;
static int bounceHeight = 20; // dp
static int bounceDuration = 1500; // ms interval per tick

static void setNotificationVisibility(String name) {
if (name.equalsIgnoreCase("visibilityPublic")) {
Expand Down
59 changes: 36 additions & 23 deletions lib/src/overlay_window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class FlutterOverlayWindow {
///
/// `enableDrag` to enable/disable dragging the overlay over the screen and default is "false"
///
/// `enableBounce` to enable/disable bouncing the overlay over the screen and default is "false"
///
/// `bounceHeight` the bounce height and default is 20
///
/// `bounceDuration` the bounce speed and default is 1500 in milliseconds
///
/// `positionGravity` the overlay postion after drag and default is [PositionGravity.none]
///
/// `startPosition` the overlay start position and default is null
Expand All @@ -50,22 +56,25 @@ class FlutterOverlayWindow {
bool enableDrag = false,
PositionGravity positionGravity = PositionGravity.none,
OverlayPosition? startPosition,
bool enableBounce = false,
int bounceHeight = 20,
int bounceDuration = 1500,
}) async {
await _channel.invokeMethod(
'showOverlay',
{
"height": height,
"width": width,
"alignment": alignment.name,
"flag": flag.name,
"overlayTitle": overlayTitle,
"overlayContent": overlayContent,
"enableDrag": enableDrag,
"notificationVisibility": visibility.name,
"positionGravity": positionGravity.name,
"startPosition": startPosition?.toMap(),
},
);
await _channel.invokeMethod('showOverlay', {
"height": height,
"width": width,
"alignment": alignment.name,
"flag": flag.name,
"overlayTitle": overlayTitle,
"overlayContent": overlayContent,
"enableDrag": enableDrag,
"notificationVisibility": visibility.name,
"positionGravity": positionGravity.name,
"startPosition": startPosition?.toMap(),
"enableBounce": enableBounce,
"bounceHeight": bounceHeight,
"bounceDuration": bounceDuration,
});
}

/// Check if overlay permission is granted
Expand Down Expand Up @@ -121,15 +130,19 @@ class FlutterOverlayWindow {
int width,
int height,
bool enableDrag,
bool enableBounce,
int bounceHeight,
int bounceDuration,
) async {
final bool? _res = await _overlayChannel.invokeMethod<bool?>(
'resizeOverlay',
{
'width': width,
'height': height,
'enableDrag': enableDrag,
},
);
final bool? _res = await _overlayChannel
.invokeMethod<bool?>('resizeOverlay', {
'width': width,
'height': height,
'enableDrag': enableDrag,
'enableBounce': enableBounce,
'bounceHeight': bounceHeight,
'bounceDuration': bounceDuration,
});
return _res;
}

Expand Down