原生开发悬浮窗 移动和支持 缩放
这里需要一些res 文件的准备 和xml 文件声明 res 中准备 layout
package com.demo;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
public class FloatingWindowService extends Service {
private WindowManager windowManager;
private View floatingView;
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private float initialDistance;
private float initialScale = 1f;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
floatingView = LayoutInflater.from(this).inflate(R.layout.float_app, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT
);
params.flags = params.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
params.x = 0;
params.y = 0;
floatingView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_POINTER_DOWN:
initialDistance = getDistance(event);
return true;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() >= 2) {
float currentDistance = getDistance(event);
float delta = currentDistance - initialDistance;
float scale = initialScale + delta * 0.01f;
floatingView.setScaleX(scale);
floatingView.setScaleY(scale);
} else {
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(floatingView, params);
}
return true;
case MotionEvent.ACTION_UP:
SharedPreferences sharedPreferences = getSharedPreferences("FloatingWindowPrefs", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("x", params.x);
editor.putInt("y", params.y);
editor.putFloat("scale", floatingView.getScaleX());
editor.apply();
return true;
}
return false;
}
private float getDistance(MotionEvent event) {
float dx = event.getX(0) - event.getX(1);
float dy = event.getY(0) - event.getY(1);
return (float) Math.sqrt(dx * dx + dy * dy);
}
});
windowManager.addView(floatingView, params);
}
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getExtras() != null) {
String paramValue = intent.getStringExtra("paramKey");
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if (floatingView != null) {
windowManager.removeView(floatingView);
}
}
}