滑动事件初步实现
This commit is contained in:
parent
21e5cd7902
commit
3e546ef48a
@ -40,6 +40,10 @@ public class AutoClickService extends AccessibilityService {
|
||||
private int screenWidth;
|
||||
private int screenHeight;
|
||||
|
||||
private final List<Slide> slideEvents = new ArrayList<>();
|
||||
private int currentEventIndex = 0;
|
||||
private int slideDuration = 500; // 新增:滑动时长
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
@ -80,6 +84,12 @@ public class AutoClickService extends AccessibilityService {
|
||||
logDebug("设置多点点击位置: " + positions.size() + " 个点");
|
||||
}
|
||||
|
||||
public void setSlideEvents(List<Slide> slides) {
|
||||
this.slideEvents.clear();
|
||||
this.slideEvents.addAll(slides);
|
||||
logDebug("设置滑动事件: " + slides.size() + " 个");
|
||||
}
|
||||
|
||||
public void setClickInterval(long interval) {
|
||||
if (interval < MIN_CLICK_INTERVAL || interval > MAX_CLICK_INTERVAL) {
|
||||
Log.w(TAG, "点击间隔超出范围: " + interval + "ms");
|
||||
@ -100,15 +110,15 @@ public class AutoClickService extends AccessibilityService {
|
||||
|
||||
public void startClicking() {
|
||||
if (!isClicking) {
|
||||
if (moreClickPositions.isEmpty() && (clickX == 0 && clickY == 0)) {
|
||||
Log.w(TAG, "无有效点击位置,忽略开始点击");
|
||||
if (moreClickPositions.isEmpty() && slideEvents.isEmpty() && (clickX == 0 && clickY == 0)) {
|
||||
Log.w(TAG, "无有效点击或滑动事件,忽略开始");
|
||||
return;
|
||||
}
|
||||
|
||||
isClicking = true;
|
||||
currentClickIndex = 0;
|
||||
logDebug("开始自动点击");
|
||||
performClick();
|
||||
currentEventIndex = 0;
|
||||
logDebug("开始自动点击/滑动");
|
||||
performEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,7 +126,7 @@ public class AutoClickService extends AccessibilityService {
|
||||
if (isClicking) {
|
||||
isClicking = false;
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
logDebug("停止自动点击");
|
||||
logDebug("停止自动点击/滑动");
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,26 +134,9 @@ public class AutoClickService extends AccessibilityService {
|
||||
return isClicking;
|
||||
}
|
||||
|
||||
private void performClick() {
|
||||
if (!isClicking) {
|
||||
logDebug("跳过点击:服务未处于运行中");
|
||||
return;
|
||||
}
|
||||
|
||||
Point clickPoint;
|
||||
int flashIndex = -1; // 新增变量,控制闪烁哪个点
|
||||
|
||||
if (!moreClickPositions.isEmpty()) {
|
||||
// 多点模式:取当前索引的点
|
||||
clickPoint = moreClickPositions.get(currentClickIndex);
|
||||
flashIndex = currentClickIndex; // 标记当前点击的是第几个点
|
||||
} else {
|
||||
// 单点模式
|
||||
clickPoint = new Point(clickX, clickY);
|
||||
}
|
||||
|
||||
private void performClick(Point clickPoint, int index) {
|
||||
logDebug("执行点击: (" + clickPoint.x + ", " + clickPoint.y + ")");
|
||||
flashTouchFeedback(flashIndex);
|
||||
flashTouchFeedback(index);
|
||||
|
||||
Path path = new Path();
|
||||
path.moveTo(clickPoint.x, clickPoint.y);
|
||||
@ -156,28 +149,86 @@ public class AutoClickService extends AccessibilityService {
|
||||
@Override
|
||||
public void onCompleted(GestureDescription gestureDescription) {
|
||||
logDebug("点击完成");
|
||||
|
||||
if (isClicking) {
|
||||
if (!moreClickPositions.isEmpty()) {
|
||||
// 多点模式:下一个触摸点
|
||||
currentClickIndex = (currentClickIndex + 1) % moreClickPositions.size();
|
||||
logDebug("当前点击点" + currentClickIndex);
|
||||
}
|
||||
// 安排下一次点击(无论是单点还是多点)
|
||||
handler.postDelayed(() -> performClick(), clickInterval);
|
||||
handler.postDelayed(() -> performEvent(), clickInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(GestureDescription gestureDescription) {
|
||||
Log.e(TAG, "点击被取消");
|
||||
|
||||
if (isClicking) {
|
||||
if (!moreClickPositions.isEmpty()) {
|
||||
currentClickIndex = (currentClickIndex + 1) % moreClickPositions.size();
|
||||
}
|
||||
// 点击取消也继续循环
|
||||
handler.postDelayed(() -> performClick(), clickInterval + 300);
|
||||
handler.postDelayed(() -> performEvent(), clickInterval + 300);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
private void performEvent() {
|
||||
if (!isClicking) {
|
||||
logDebug("跳过事件:服务未处于运行中");
|
||||
return;
|
||||
}
|
||||
|
||||
if (moreClickPositions.isEmpty() && slideEvents.isEmpty()) {
|
||||
if (clickX != 0 || clickY != 0) {
|
||||
// 单点模式
|
||||
performClick(new Point(clickX, clickY), -1);
|
||||
return;
|
||||
}
|
||||
stopClicking();
|
||||
return;
|
||||
}
|
||||
|
||||
// 多点模式:按事件队列顺序执行
|
||||
int pointIndex = 0;
|
||||
int slideIndex = 0;
|
||||
for (int i = 0; i <= currentEventIndex; i++) {
|
||||
if (pointIndex < moreClickPositions.size() && i == pointIndex) {
|
||||
pointIndex++;
|
||||
} else if (slideIndex < slideEvents.size()) {
|
||||
slideIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pointIndex > currentEventIndex) {
|
||||
// 执行点击
|
||||
Point clickPoint = moreClickPositions.get(pointIndex - 1);
|
||||
performClick(clickPoint, pointIndex - 1);
|
||||
} else if (slideIndex > currentEventIndex) {
|
||||
// 执行滑动
|
||||
Slide slide = slideEvents.get(slideIndex - 1);
|
||||
performSlide(slide);
|
||||
}
|
||||
|
||||
currentEventIndex = (currentEventIndex + 1) % (moreClickPositions.size() + slideEvents.size());
|
||||
}
|
||||
|
||||
private void performSlide(Slide slide) {
|
||||
logDebug("执行滑动: 从 (" + slide.startX + ", " + slide.startY + ") 到 (" + slide.endX + ", " + slide.endY + ")");
|
||||
|
||||
Path path = new Path();
|
||||
path.moveTo(slide.startX, slide.startY);
|
||||
path.lineTo(slide.endX, slide.endY);
|
||||
GestureDescription.StrokeDescription stroke =
|
||||
new GestureDescription.StrokeDescription(path, 0, slideDuration);
|
||||
GestureDescription gesture =
|
||||
new GestureDescription.Builder().addStroke(stroke).build();
|
||||
|
||||
dispatchGesture(gesture, new GestureResultCallback() {
|
||||
@Override
|
||||
public void onCompleted(GestureDescription gestureDescription) {
|
||||
logDebug("滑动完成");
|
||||
if (isClicking) {
|
||||
handler.postDelayed(() -> performEvent(), clickInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(GestureDescription gestureDescription) {
|
||||
Log.e(TAG, "滑动被取消");
|
||||
if (isClicking) {
|
||||
handler.postDelayed(() -> performEvent(), clickInterval + 300);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.auto.autoclicker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.view.View;
|
||||
|
||||
public class ConnectingLineView extends View {
|
||||
private float startX, startY, endX, endY;
|
||||
private Paint paint;
|
||||
|
||||
public ConnectingLineView(Context context) {
|
||||
super(context);
|
||||
paint = new Paint();
|
||||
paint.setColor(Color.RED);
|
||||
paint.setAlpha(180);
|
||||
paint.setStrokeWidth(5);
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
// 直接在全屏视图上绘制线条
|
||||
canvas.drawLine(startX, startY, endX, endY, paint);
|
||||
}
|
||||
|
||||
public void setPoints(float startX, float startY, float endX, float endY) {
|
||||
this.startX = startX;
|
||||
this.startY = startY;
|
||||
this.endX = endX;
|
||||
this.endY = endY;
|
||||
invalidate(); // 请求重绘
|
||||
}
|
||||
}
|
||||
5
app/src/main/java/com/auto/autoclicker/Event.java
Normal file
5
app/src/main/java/com/auto/autoclicker/Event.java
Normal file
@ -0,0 +1,5 @@
|
||||
package com.auto.autoclicker;
|
||||
|
||||
public interface Event {
|
||||
int getId();
|
||||
}
|
||||
@ -6,6 +6,7 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.os.Build;
|
||||
@ -66,6 +67,9 @@ public class FloatingViewManager {
|
||||
private final int screenWidth;
|
||||
private final int screenHeight;
|
||||
|
||||
private final List<Event> eventQueue = new ArrayList<>(); // 事件队列
|
||||
private int eventIdCounter = 1; // 事件编号
|
||||
|
||||
public FloatingViewManager(Context context) {
|
||||
this.context = context;
|
||||
this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
@ -166,6 +170,8 @@ public class FloatingViewManager {
|
||||
private void initMoreTouchPointView() {
|
||||
moreTouchPointViews.clear();
|
||||
moreTouchPointParams.clear();
|
||||
eventQueue.clear(); // 清空事件队列
|
||||
eventIdCounter = 1; // 重置编号
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@ -271,9 +277,9 @@ public class FloatingViewManager {
|
||||
ImageView settingButton = moreControlBarView.findViewById(R.id.settings_button);
|
||||
|
||||
playButton.setOnClickListener(v -> toggleMoreClicking());
|
||||
addButton.setOnClickListener(v -> addMoreTouchPoint());
|
||||
removeButton.setOnClickListener(v -> removeMoreTouchPoint());
|
||||
|
||||
addButton.setOnClickListener(v -> addPointEvent());
|
||||
removeButton.setOnClickListener(v -> removeLastEvent());
|
||||
slideButton.setOnClickListener(v -> addSlideEvent());
|
||||
closeButton.setOnClickListener(v -> closeFloatingViews());
|
||||
settingButton.setOnClickListener(v -> showInputDialog());
|
||||
}
|
||||
@ -334,6 +340,37 @@ public class FloatingViewManager {
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
// private void toggleMoreClicking() {
|
||||
// if (isDebounced()) return;
|
||||
//
|
||||
// AutoClickService service = AutoClickService.getInstance();
|
||||
// if (service == null) {
|
||||
// Log.e(TAG, "AutoClickService 未初始化");
|
||||
// Toast.makeText(context, "请在设置中启用无障碍服务", Toast.LENGTH_LONG).show();
|
||||
// Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// context.startActivity(intent);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (moreTouchPointViews.isEmpty()) {
|
||||
// Toast.makeText(context, "请先添加触摸点", Toast.LENGTH_SHORT).show();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (isMoreClicking) {
|
||||
// service.stopClicking();
|
||||
// Toast.makeText(context, "停止多点点击", Toast.LENGTH_SHORT).show();
|
||||
// } else {
|
||||
// service.setMoreClickPositions(getMoreTouchPositions());
|
||||
// service.startClicking();
|
||||
// Toast.makeText(context, "开始多点点击", Toast.LENGTH_SHORT).show();
|
||||
// }
|
||||
//
|
||||
// isMoreClicking = !isMoreClicking;
|
||||
// logDebug("多点服务是否点击中: " + service.isClicking());
|
||||
// }
|
||||
|
||||
private void toggleMoreClicking() {
|
||||
if (isDebounced()) return;
|
||||
|
||||
@ -341,22 +378,26 @@ public class FloatingViewManager {
|
||||
if (service == null) {
|
||||
Log.e(TAG, "AutoClickService 未初始化");
|
||||
Toast.makeText(context, "请在设置中启用无障碍服务", Toast.LENGTH_LONG).show();
|
||||
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
|
||||
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (moreTouchPointViews.isEmpty()) {
|
||||
Toast.makeText(context, "请先添加触摸点", Toast.LENGTH_SHORT).show();
|
||||
if (eventQueue.isEmpty()) {
|
||||
Toast.makeText(context, "请先添加触摸点或滑动事件", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMoreClicking) {
|
||||
service.stopClicking();
|
||||
Toast.makeText(context, "停止多点点击", Toast.LENGTH_SHORT).show();
|
||||
for (View point : moreTouchPointViews) {
|
||||
point.setBackgroundResource(R.drawable.un_touch_point);
|
||||
}
|
||||
} else {
|
||||
service.setMoreClickPositions(getMoreTouchPositions());
|
||||
service.setSlideEvents(getSlideEvents());
|
||||
service.startClicking();
|
||||
Toast.makeText(context, "开始多点点击", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@ -438,6 +479,319 @@ public class FloatingViewManager {
|
||||
moreTouchPointParams.add(params);
|
||||
}
|
||||
|
||||
private void addPointEvent() {
|
||||
View point = new View(context);
|
||||
point.setBackgroundResource(R.drawable.un_touch_point);
|
||||
|
||||
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
||||
100, 100,
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_PHONE,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
|
||||
PixelFormat.TRANSLUCENT
|
||||
);
|
||||
params.gravity = Gravity.TOP | Gravity.START;
|
||||
params.x = screenWidth / 2 - 50;
|
||||
params.y = screenHeight / 2 - 50;
|
||||
|
||||
PointEvent pointEvent = new PointEvent(eventIdCounter++, params.x, params.y, point, params);
|
||||
eventQueue.add(pointEvent);
|
||||
moreTouchPointViews.add(point);
|
||||
moreTouchPointParams.add(params);
|
||||
|
||||
point.setOnTouchListener(new View.OnTouchListener() {
|
||||
private float lastX, lastY;
|
||||
private float paramX, paramY;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
lastX = event.getRawX();
|
||||
lastY = event.getRawY();
|
||||
paramX = params.x;
|
||||
paramY = params.y;
|
||||
return true;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float dx = event.getRawX() - lastX;
|
||||
float dy = event.getRawY() - lastY;
|
||||
Point constrainedPoint = ViewUtils.constrainToScreen(
|
||||
paramX + dx, paramY + dy,
|
||||
screenWidth - point.getWidth(), screenHeight - point.getHeight());
|
||||
params.x = constrainedPoint.x;
|
||||
params.y = constrainedPoint.y;
|
||||
pointEvent.x = params.x;
|
||||
pointEvent.y = params.y;
|
||||
windowManager.updateViewLayout(point, params);
|
||||
updateServicePositions();
|
||||
return true;
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
windowManager.addView(point, params);
|
||||
updateServicePositions();
|
||||
}
|
||||
|
||||
private void addSlideEvent() {
|
||||
// 起点
|
||||
View startPoint = new View(context);
|
||||
startPoint.setBackgroundResource(R.drawable.un_touch_point);
|
||||
WindowManager.LayoutParams startParams = new WindowManager.LayoutParams(
|
||||
100, 100,
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_PHONE,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
|
||||
PixelFormat.TRANSLUCENT
|
||||
);
|
||||
startParams.gravity = Gravity.TOP | Gravity.START;
|
||||
startParams.x = screenWidth / 2 - 100;
|
||||
startParams.y = screenHeight / 2 - 50;
|
||||
PointEvent startPointEvent = new PointEvent(eventIdCounter++, startParams.x, startParams.y, startPoint, startParams);
|
||||
|
||||
// 终点
|
||||
View endPoint = new View(context);
|
||||
endPoint.setBackgroundResource(R.drawable.un_touch_point);
|
||||
WindowManager.LayoutParams endParams = new WindowManager.LayoutParams(
|
||||
100, 100,
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_PHONE,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
|
||||
PixelFormat.TRANSLUCENT
|
||||
);
|
||||
endParams.gravity = Gravity.TOP | Gravity.START;
|
||||
endParams.x = screenWidth / 2 + 100;
|
||||
endParams.y = screenHeight / 2 - 50;
|
||||
PointEvent endPointEvent = new PointEvent(eventIdCounter++, endParams.x, endParams.y, endPoint, endParams);
|
||||
|
||||
// 创建连接线视图 - 关键是使用全屏大小
|
||||
ConnectingLineView lineView = new ConnectingLineView(context);
|
||||
WindowManager.LayoutParams lineParams = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT, // 全屏宽度
|
||||
WindowManager.LayoutParams.MATCH_PARENT, // 全屏高度
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_PHONE,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, // 不接收触摸事件
|
||||
PixelFormat.TRANSLUCENT
|
||||
);
|
||||
lineParams.gravity = Gravity.TOP | Gravity.START;
|
||||
lineParams.x = 0; // 从屏幕左上角开始
|
||||
lineParams.y = 0;
|
||||
|
||||
SlideEvent slideEvent = new SlideEvent(eventIdCounter++, startPointEvent, endPointEvent, lineView, lineParams);
|
||||
eventQueue.add(slideEvent);
|
||||
moreTouchPointViews.add(startPoint);
|
||||
moreTouchPointViews.add(endPoint);
|
||||
moreTouchPointParams.add(startParams);
|
||||
moreTouchPointParams.add(endParams);
|
||||
|
||||
// 起点拖动监听
|
||||
startPoint.setOnTouchListener(new View.OnTouchListener() {
|
||||
private float lastX, lastY;
|
||||
private float paramX, paramY;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
lastX = event.getRawX();
|
||||
lastY = event.getRawY();
|
||||
paramX = startParams.x;
|
||||
paramY = startParams.y;
|
||||
return true;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float dx = event.getRawX() - lastX;
|
||||
float dy = event.getRawY() - lastY;
|
||||
Point constrainedPoint = ViewUtils.constrainToScreen(
|
||||
paramX + dx, paramY + dy,
|
||||
screenWidth - startPoint.getWidth(), screenHeight - startPoint.getHeight());
|
||||
startParams.x = constrainedPoint.x;
|
||||
startParams.y = constrainedPoint.y;
|
||||
startPointEvent.x = startParams.x;
|
||||
startPointEvent.y = startParams.y;
|
||||
windowManager.updateViewLayout(startPoint, startParams);
|
||||
|
||||
// 更新连接线
|
||||
updateLinePosition(slideEvent);
|
||||
updateServicePositions();
|
||||
return true;
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// 终点拖动监听
|
||||
endPoint.setOnTouchListener(new View.OnTouchListener() {
|
||||
private float lastX, lastY;
|
||||
private float paramX, paramY;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
lastX = event.getRawX();
|
||||
lastY = event.getRawY();
|
||||
paramX = endParams.x;
|
||||
paramY = endParams.y;
|
||||
return true;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float dx = event.getRawX() - lastX;
|
||||
float dy = event.getRawY() - lastY;
|
||||
Point constrainedPoint = ViewUtils.constrainToScreen(
|
||||
paramX + dx, paramY + dy,
|
||||
screenWidth - endPoint.getWidth(), screenHeight - endPoint.getHeight());
|
||||
endParams.x = constrainedPoint.x;
|
||||
endParams.y = constrainedPoint.y;
|
||||
endPointEvent.x = endParams.x;
|
||||
endPointEvent.y = endParams.y;
|
||||
windowManager.updateViewLayout(endPoint, endParams);
|
||||
|
||||
// 更新连接线
|
||||
updateLinePosition(slideEvent);
|
||||
|
||||
updateServicePositions();
|
||||
return true;
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// 首先添加连接线,确保它在最下层
|
||||
windowManager.addView(lineView, lineParams);
|
||||
windowManager.addView(startPoint, startParams);
|
||||
windowManager.addView(endPoint, endParams);
|
||||
|
||||
// 初始化连接线位置
|
||||
updateLinePosition(slideEvent);
|
||||
updateServicePositions();
|
||||
}
|
||||
|
||||
// 更新连接线位置的方法
|
||||
private void updateLinePosition(SlideEvent slideEvent) {
|
||||
PointEvent start = slideEvent.startPoint;
|
||||
PointEvent end = slideEvent.endPoint;
|
||||
ConnectingLineView lineView = (ConnectingLineView) slideEvent.lineView;
|
||||
|
||||
// 计算两点中心位置
|
||||
float startCenterX = start.x + 50; // 假设点的宽度为100
|
||||
float startCenterY = start.y + 50;
|
||||
float endCenterX = end.x + 50;
|
||||
float endCenterY = end.y + 50;
|
||||
|
||||
// 更新线条位置 - 直接设置线条的起点和终点
|
||||
lineView.setPoints(startCenterX, startCenterY, endCenterX, endCenterY);
|
||||
}
|
||||
|
||||
private void updateLineView(SlideEvent slideEvent) {
|
||||
WindowManager.LayoutParams lineParams = slideEvent.lineParams;
|
||||
PointEvent start = slideEvent.startPoint;
|
||||
PointEvent end = slideEvent.endPoint;
|
||||
View lineView = slideEvent.lineView;
|
||||
|
||||
// 计算两点中心位置
|
||||
float startCenterX = start.x + 50; // 假设点的宽度为100,中心点坐标为x+50
|
||||
float startCenterY = start.y + 50; // 假设点的高度为100,中心点坐标为y+50
|
||||
float endCenterX = end.x + 50;
|
||||
float endCenterY = end.y + 50;
|
||||
|
||||
// 计算两点之间的距离和角度
|
||||
float deltaX = endCenterX - startCenterX;
|
||||
float deltaY = endCenterY - startCenterY;
|
||||
float distance = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
|
||||
|
||||
// 设置连接线的宽度为两点之间的距离
|
||||
lineParams.width = (int) distance;
|
||||
lineParams.height = 5; // 固定高度
|
||||
|
||||
// 设置连接线的起始位置为起始点的中心
|
||||
lineParams.x = (int) startCenterX;
|
||||
lineParams.y = (int) startCenterY - lineParams.height / 2; // 垂直居中
|
||||
|
||||
// 由于线条是从左到右绘制的,我们需要设置旋转中心点
|
||||
lineView.setPivotX(0); // 设置旋转中心为线条的起点
|
||||
lineView.setPivotY(lineParams.height / 2); // 设置旋转中心为线条高度的一半
|
||||
|
||||
// 设置连接线的旋转角度
|
||||
lineView.setRotation(angle);
|
||||
|
||||
// 更新连接线的布局
|
||||
windowManager.updateViewLayout(lineView, lineParams);
|
||||
}
|
||||
|
||||
// 新增:移除最后一个事件
|
||||
private void removeLastEvent() {
|
||||
if (eventQueue.isEmpty()) {
|
||||
Toast.makeText(context, "没有更多事件可以删除", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Event lastEvent = eventQueue.remove(eventQueue.size() - 1);
|
||||
if (lastEvent instanceof PointEvent) {
|
||||
PointEvent pointEvent = (PointEvent) lastEvent;
|
||||
try {
|
||||
windowManager.removeView(pointEvent.view);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "移除触摸点失败", e);
|
||||
}
|
||||
moreTouchPointViews.remove(pointEvent.view);
|
||||
moreTouchPointParams.remove(pointEvent.params);
|
||||
} else if (lastEvent instanceof SlideEvent) {
|
||||
SlideEvent slideEvent = (SlideEvent) lastEvent;
|
||||
try {
|
||||
windowManager.removeView(slideEvent.startPoint.view);
|
||||
windowManager.removeView(slideEvent.endPoint.view);
|
||||
windowManager.removeView(slideEvent.lineView);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "移除滑动事件失败", e);
|
||||
}
|
||||
moreTouchPointViews.remove(slideEvent.startPoint.view);
|
||||
moreTouchPointViews.remove(slideEvent.endPoint.view);
|
||||
moreTouchPointParams.remove(slideEvent.startPoint.params);
|
||||
moreTouchPointParams.remove(slideEvent.endPoint.params);
|
||||
}
|
||||
updateServicePositions();
|
||||
}
|
||||
|
||||
// 新增:同步事件位置到 AutoClickService
|
||||
private void updateServicePositions() {
|
||||
List<Point> points = new ArrayList<>();
|
||||
List<Slide> slides = new ArrayList<>();
|
||||
for (Event event : eventQueue) {
|
||||
if (event instanceof PointEvent) {
|
||||
PointEvent pe = (PointEvent) event;
|
||||
points.add(new Point((int) pe.x, (int) pe.y));
|
||||
} else if (event instanceof SlideEvent) {
|
||||
SlideEvent se = (SlideEvent) event;
|
||||
slides.add(new Slide(se.startPoint.x, se.startPoint.y, se.endPoint.x, se.endPoint.y));
|
||||
}
|
||||
}
|
||||
AutoClickService service = AutoClickService.getInstance();
|
||||
if (service != null) {
|
||||
service.setMoreClickPositions(points);
|
||||
service.setSlideEvents(slides);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeMoreTouchPoint() {
|
||||
if (!moreTouchPointViews.isEmpty()) {
|
||||
View lastPoint = moreTouchPointViews.get(moreTouchPointViews.size() - 1);
|
||||
@ -477,6 +831,18 @@ public class FloatingViewManager {
|
||||
}
|
||||
moreTouchPointParams.clear(); // 清空参数列表
|
||||
|
||||
for (Event event : new ArrayList<>(eventQueue)) {
|
||||
if (event instanceof SlideEvent) {
|
||||
SlideEvent se = (SlideEvent) event;
|
||||
try {
|
||||
windowManager.removeView(se.lineView);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "移除滑动线失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
eventQueue.clear();
|
||||
|
||||
// 移除单点控制栏
|
||||
if (singleControlBarView != null) {
|
||||
try {
|
||||
@ -498,10 +864,12 @@ public class FloatingViewManager {
|
||||
}
|
||||
|
||||
isClicking = false;
|
||||
isMoreClicking = false;
|
||||
logDebug("悬浮窗已移除");
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "移除悬浮窗失败", e);
|
||||
isClicking = false;
|
||||
isMoreClicking = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,6 +956,18 @@ public class FloatingViewManager {
|
||||
});
|
||||
}
|
||||
|
||||
// 新增:获取滑动事件列表
|
||||
private List<Slide> getSlideEvents() {
|
||||
List<Slide> slides = new ArrayList<>();
|
||||
for (Event event : eventQueue) {
|
||||
if (event instanceof SlideEvent) {
|
||||
SlideEvent se = (SlideEvent) event;
|
||||
slides.add(new Slide(se.startPoint.x, se.startPoint.y, se.endPoint.x, se.endPoint.y));
|
||||
}
|
||||
}
|
||||
return slides;
|
||||
}
|
||||
|
||||
// 改成只闪烁当前索引的触摸点
|
||||
public void flashTouchPoint(int index) {
|
||||
if (index == -1) {
|
||||
|
||||
24
app/src/main/java/com/auto/autoclicker/PointEvent.java
Normal file
24
app/src/main/java/com/auto/autoclicker/PointEvent.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.auto.autoclicker;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class PointEvent implements Event {
|
||||
int id;
|
||||
float x, y;
|
||||
View view;
|
||||
WindowManager.LayoutParams params;
|
||||
|
||||
PointEvent(int id, float x, float y, View view, WindowManager.LayoutParams params) {
|
||||
this.id = id;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.view = view;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
12
app/src/main/java/com/auto/autoclicker/Slide.java
Normal file
12
app/src/main/java/com/auto/autoclicker/Slide.java
Normal file
@ -0,0 +1,12 @@
|
||||
package com.auto.autoclicker;
|
||||
|
||||
public class Slide {
|
||||
float startX, startY, endX, endY;
|
||||
|
||||
Slide(float startX, float startY, float endX, float endY) {
|
||||
this.startX = startX;
|
||||
this.startY = startY;
|
||||
this.endX = endX;
|
||||
this.endY = endY;
|
||||
}
|
||||
}
|
||||
25
app/src/main/java/com/auto/autoclicker/SlideEvent.java
Normal file
25
app/src/main/java/com/auto/autoclicker/SlideEvent.java
Normal file
@ -0,0 +1,25 @@
|
||||
package com.auto.autoclicker;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class SlideEvent implements Event {
|
||||
int id;
|
||||
PointEvent startPoint;
|
||||
PointEvent endPoint;
|
||||
View lineView;
|
||||
WindowManager.LayoutParams lineParams;
|
||||
|
||||
SlideEvent(int id, PointEvent startPoint, PointEvent endPoint, View lineView, WindowManager.LayoutParams lineParams) {
|
||||
this.id = id;
|
||||
this.startPoint = startPoint;
|
||||
this.endPoint = endPoint;
|
||||
this.lineView = lineView;
|
||||
this.lineParams = lineParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user