完善单个点击
This commit is contained in:
parent
e5f52aaba3
commit
60d264e131
@ -12,14 +12,21 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.auto.autoclicker.util.ScreenUtils;
|
||||
import com.auto.autoclicker.util.ViewUtils;
|
||||
|
||||
public class AutoClickService extends AccessibilityService {
|
||||
private static final String TAG = "AutoClickService";
|
||||
private static final long MIN_CLICK_INTERVAL = 100;
|
||||
private static AutoClickService instance;
|
||||
|
||||
private static final long MIN_CLICK_INTERVAL = 40;
|
||||
private static final long MAX_CLICK_INTERVAL = 10000;
|
||||
private static final int MIN_CLICK_DURATION = 50;
|
||||
private static final int MAX_CLICK_DURATION = 1000;
|
||||
|
||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||
private boolean isClicking = false;
|
||||
|
||||
private int clickX = 500;
|
||||
private int clickY = 500;
|
||||
private long clickInterval = 1000;
|
||||
@ -30,46 +37,69 @@ public class AutoClickService extends AccessibilityService {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
instance = this;
|
||||
Point screenSize = ScreenUtils.getScreenSize(this);
|
||||
screenWidth = screenSize.x;
|
||||
screenHeight = screenSize.y;
|
||||
logDebug("屏幕尺寸: " + screenWidth + "x" + screenHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
super.onServiceConnected();
|
||||
logDebug("无障碍服务已连接");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
stopClicking();
|
||||
logDebug("无障碍服务中断");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
instance = null;
|
||||
stopClicking();
|
||||
Intent intent = new Intent("com.auto.autoclicker.SERVICE_DESTROYED");
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
|
||||
logDebug("无障碍服务已销毁");
|
||||
}
|
||||
|
||||
public static AutoClickService getInstance() {
|
||||
return null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void setClickPosition(float x, float y) {
|
||||
Point constrainedPoint = ViewUtils.constrainToScreen(x, y, screenWidth, screenHeight);
|
||||
this.clickX = constrainedPoint.x;
|
||||
this.clickY = constrainedPoint.y;
|
||||
logDebug("设置点击位置: x=" + x + ", y=" + y + ", 修正后: (" + clickX + ", " + clickY + ")");
|
||||
Point constrained = ViewUtils.constrainToScreen(x, y, screenWidth, screenHeight);
|
||||
this.clickX = constrained.x;
|
||||
this.clickY = constrained.y;
|
||||
logDebug("设置点击位置: 原始 (" + x + ", " + y + ") -> 修正 (" + clickX + ", " + clickY + ")");
|
||||
}
|
||||
|
||||
public void setClickInterval(long interval) {
|
||||
if (interval < MIN_CLICK_INTERVAL || interval > MAX_CLICK_INTERVAL) {
|
||||
Log.w(TAG, "点击间隔超出合理范围: " + interval + "ms");
|
||||
Log.w(TAG, "点击间隔超出范围: " + interval + "ms");
|
||||
return;
|
||||
}
|
||||
this.clickInterval = interval;
|
||||
logDebug("点击间隔设置为: " + interval + "ms");
|
||||
logDebug("设置点击间隔: " + interval + "ms");
|
||||
}
|
||||
|
||||
public void setClickDuration(int duration) {
|
||||
if (duration < MIN_CLICK_DURATION || duration > MAX_CLICK_DURATION) {
|
||||
Log.w(TAG, "点击时长超出合理范围: " + duration + "ms");
|
||||
Log.w(TAG, "点击时长超出范围: " + duration + "ms");
|
||||
return;
|
||||
}
|
||||
this.clickDuration = duration;
|
||||
logDebug("点击时长设置为: " + duration + "ms");
|
||||
logDebug("设置点击时长: " + duration + "ms");
|
||||
}
|
||||
|
||||
public void startClicking() {
|
||||
if (!isClicking) {
|
||||
isClicking = true;
|
||||
logDebug("开始自动点击");
|
||||
performClick();
|
||||
logDebug("开始点击: (" + clickX + ", " + clickY + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,17 +107,23 @@ public class AutoClickService extends AccessibilityService {
|
||||
if (isClicking) {
|
||||
isClicking = false;
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
logDebug("停止点击");
|
||||
logDebug("停止自动点击");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isClicking() {
|
||||
return isClicking;
|
||||
}
|
||||
|
||||
private void performClick() {
|
||||
if (!isClicking) {
|
||||
logDebug("点击被跳过(未开始)");
|
||||
logDebug("跳过点击:服务未处于运行中");
|
||||
return;
|
||||
}
|
||||
|
||||
logDebug("执行点击: (" + clickX + ", " + clickY + ")");
|
||||
flashTouchFeedback();
|
||||
|
||||
Path path = new Path();
|
||||
path.moveTo(clickX, clickY);
|
||||
GestureDescription.StrokeDescription stroke =
|
||||
@ -98,7 +134,7 @@ public class AutoClickService extends AccessibilityService {
|
||||
dispatchGesture(gesture, new GestureResultCallback() {
|
||||
@Override
|
||||
public void onCompleted(GestureDescription gestureDescription) {
|
||||
logDebug("点击完成: (" + clickX + ", " + clickY + ")");
|
||||
logDebug("点击完成");
|
||||
if (isClicking) {
|
||||
handler.postDelayed(() -> performClick(), clickInterval);
|
||||
}
|
||||
@ -106,7 +142,7 @@ public class AutoClickService extends AccessibilityService {
|
||||
|
||||
@Override
|
||||
public void onCancelled(GestureDescription gestureDescription) {
|
||||
Log.e(TAG, "点击取消: (" + clickX + ", " + clickY + ")");
|
||||
Log.e(TAG, "点击被取消");
|
||||
if (isClicking) {
|
||||
handler.postDelayed(() -> performClick(), clickInterval + 300);
|
||||
}
|
||||
@ -114,35 +150,17 @@ public class AutoClickService extends AccessibilityService {
|
||||
}, null);
|
||||
}
|
||||
|
||||
private void flashTouchFeedback() {
|
||||
FloatingViewManager manager = FloatingViewManager.getInstance();
|
||||
if (manager != null) {
|
||||
manager.flashTouchPoint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
stopClicking();
|
||||
logDebug("无障碍服务中断");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceConnected() {
|
||||
super.onServiceConnected();
|
||||
logDebug("无障碍服务已连接");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
stopClicking();
|
||||
Intent intent = new Intent("com.auto.autoclicker.SERVICE_DESTROYED");
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
|
||||
logDebug("无障碍服务已销毁");
|
||||
}
|
||||
|
||||
public boolean isClicking() {
|
||||
return isClicking;
|
||||
}
|
||||
|
||||
private void logDebug(String message) {
|
||||
Log.d(TAG, message);
|
||||
}
|
||||
|
||||
@ -1,24 +1,38 @@
|
||||
package com.auto.autoclicker;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.auto.autoclicker.util.ScreenUtils;
|
||||
import com.auto.autoclicker.util.ViewUtils;
|
||||
|
||||
public class FloatingViewManager {
|
||||
private static final String TAG = "FloatingViewManager";
|
||||
private static final long DEBOUNCE_INTERVAL = 500;
|
||||
|
||||
private static FloatingViewManager instance;
|
||||
|
||||
private final Context context;
|
||||
private final WindowManager windowManager;
|
||||
private View touchPointView;
|
||||
@ -32,9 +46,11 @@ public class FloatingViewManager {
|
||||
private long lastToggleTime = 0;
|
||||
private final int screenWidth;
|
||||
private final int screenHeight;
|
||||
private final AutoClickService service = AutoClickService.getInstance();
|
||||
|
||||
public FloatingViewManager(Context context) {
|
||||
this.context = context;
|
||||
instance = this;
|
||||
this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Point screenSize = ScreenUtils.getScreenSize(context);
|
||||
this.screenWidth = screenSize.x;
|
||||
@ -42,6 +58,10 @@ public class FloatingViewManager {
|
||||
logDebug("屏幕尺寸: " + screenWidth + "x" + screenHeight);
|
||||
}
|
||||
|
||||
public static FloatingViewManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void showFloatingViews() throws SecurityException {
|
||||
if (!Settings.canDrawOverlays(context)) {
|
||||
throw new SecurityException("需要悬浮窗权限");
|
||||
@ -61,6 +81,24 @@ public class FloatingViewManager {
|
||||
logDebug("悬浮窗已添加");
|
||||
}
|
||||
|
||||
public void removeFloatingViews() {
|
||||
try {
|
||||
if (touchPointView != null) {
|
||||
windowManager.removeView(touchPointView);
|
||||
touchPointView = null;
|
||||
}
|
||||
if (controlBarView != null) {
|
||||
windowManager.removeView(controlBarView);
|
||||
controlBarView = null;
|
||||
}
|
||||
isFloatingViewsShown = false;
|
||||
logDebug("悬浮窗已移除");
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "移除悬浮窗失败", e);
|
||||
isFloatingViewsShown = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeTouchPointView() {
|
||||
touchPointView = new View(context);
|
||||
touchPointView.setBackgroundResource(R.drawable.un_touch_point);
|
||||
@ -106,16 +144,7 @@ public class FloatingViewManager {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateTouchPointPosition(float paramX, float paramY, float dx, float dy) {
|
||||
Point constrainedPoint = ViewUtils.constrainToScreen(
|
||||
paramX + dx, paramY + dy, screenWidth - touchPointView.getWidth(), screenHeight - touchPointView.getHeight());
|
||||
touchPointParams.x = constrainedPoint.x;
|
||||
touchPointParams.y = constrainedPoint.y;
|
||||
touchPointX = touchPointParams.x;
|
||||
touchPointY = touchPointParams.y;
|
||||
windowManager.updateViewLayout(touchPointView, touchPointParams);
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void initializeControlBarView() {
|
||||
controlBarView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.control_bar, null);
|
||||
controlBarParams = new WindowManager.LayoutParams(
|
||||
@ -150,18 +179,21 @@ public class FloatingViewManager {
|
||||
float dy = event.getRawY() - lastY;
|
||||
updateControlBarPosition(paramX, paramY, dx, dy);
|
||||
return true;
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Button toggleButton = controlBarView.findViewById(R.id.toggle_button);
|
||||
toggleButton.setOnClickListener(v -> {
|
||||
if (!isDebounced()) {
|
||||
return;
|
||||
}
|
||||
ImageView play = controlBarView.findViewById(R.id.play_button);
|
||||
ImageView close = controlBarView.findViewById(R.id.close_button);
|
||||
ImageView setting = controlBarView.findViewById(R.id.settings_button);
|
||||
|
||||
play.setOnClickListener(v -> {
|
||||
if (!isDebounced()) return;
|
||||
|
||||
AutoClickService service = AutoClickService.getInstance();
|
||||
if (service == null) {
|
||||
Log.e(TAG, "AutoClickService 未初始化");
|
||||
Toast.makeText(context, "请在设置中启用无障碍服务", Toast.LENGTH_LONG).show();
|
||||
@ -173,13 +205,13 @@ public class FloatingViewManager {
|
||||
|
||||
if (isClicking) {
|
||||
service.stopClicking();
|
||||
toggleButton.setText(R.string.start_click);
|
||||
play.setBackgroundResource(R.drawable.play);
|
||||
touchPointView.setBackgroundResource(R.drawable.un_touch_point);
|
||||
Toast.makeText(context, "停止自动点击", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
service.setClickPosition(touchPointX + 50, touchPointY + 50);
|
||||
service.setClickPosition(touchPointX, touchPointY);
|
||||
service.startClicking();
|
||||
toggleButton.setText(R.string.stop_click);
|
||||
play.setBackgroundResource(R.drawable.play);
|
||||
touchPointView.setBackgroundResource(R.drawable.touch_point);
|
||||
Toast.makeText(context, "开始自动点击", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@ -187,6 +219,25 @@ public class FloatingViewManager {
|
||||
isClicking = !isClicking;
|
||||
logDebug("服务是否点击中: " + service.isClicking());
|
||||
});
|
||||
|
||||
close.setOnClickListener(v -> {
|
||||
service.stopClicking();
|
||||
touchPointView.setBackgroundResource(R.drawable.un_touch_point);
|
||||
removeFloatingViews();
|
||||
});
|
||||
|
||||
setting.setOnClickListener(v -> showInputDialog());
|
||||
|
||||
}
|
||||
|
||||
private void updateTouchPointPosition(float paramX, float paramY, float dx, float dy) {
|
||||
Point constrainedPoint = ViewUtils.constrainToScreen(
|
||||
paramX + dx, paramY + dy, screenWidth - touchPointView.getWidth(), screenHeight - touchPointView.getHeight());
|
||||
touchPointParams.x = constrainedPoint.x;
|
||||
touchPointParams.y = constrainedPoint.y;
|
||||
touchPointX = touchPointParams.x;
|
||||
touchPointY = touchPointParams.y;
|
||||
windowManager.updateViewLayout(touchPointView, touchPointParams);
|
||||
}
|
||||
|
||||
private void updateControlBarPosition(float paramX, float paramY, float dx, float dy) {
|
||||
@ -197,6 +248,72 @@ public class FloatingViewManager {
|
||||
windowManager.updateViewLayout(controlBarView, controlBarParams);
|
||||
}
|
||||
|
||||
public void showInputDialog() {
|
||||
EditText input = new EditText(context);
|
||||
input.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
input.setHint("输入点击间隔(ms)");
|
||||
input.setFocusableInTouchMode(true);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle("设置点击间隔")
|
||||
.setView(input)
|
||||
.setPositiveButton("确定", (dialog, which) -> {
|
||||
String value = input.getText().toString();
|
||||
try {
|
||||
long interval = Long.parseLong(value);
|
||||
AutoClickService service = AutoClickService.getInstance();
|
||||
if (service != null) {
|
||||
service.setClickInterval(interval);
|
||||
} else {
|
||||
Log.w("InputDialog", "AutoClickService 未初始化");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Toast.makeText(context, "无效输入", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton("取消", (dialog, which) -> dialog.dismiss());
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
|
||||
// 设置弹窗的类型,允许在悬浮窗中显示输入框
|
||||
if (!(context instanceof Activity)) {
|
||||
if (dialog.getWindow() != null) {
|
||||
dialog.getWindow().setType(
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
||||
WindowManager.LayoutParams.TYPE_PHONE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
|
||||
// 强制显示软键盘
|
||||
input.requestFocus();
|
||||
input.post(() -> {
|
||||
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm != null) {
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void flashTouchPoint() {
|
||||
if (touchPointView == null) return;
|
||||
|
||||
touchPointView.animate()
|
||||
.alpha(0.3f)
|
||||
.setDuration(100)
|
||||
.withEndAction(() ->
|
||||
touchPointView.animate()
|
||||
.alpha(1.0f)
|
||||
.setDuration(100)
|
||||
.start()
|
||||
)
|
||||
.start();
|
||||
}
|
||||
|
||||
private boolean isDebounced() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime - lastToggleTime < DEBOUNCE_INTERVAL) {
|
||||
@ -206,25 +323,7 @@ public class FloatingViewManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeFloatingViews() {
|
||||
try {
|
||||
if (touchPointView != null) {
|
||||
windowManager.removeView(touchPointView);
|
||||
touchPointView = null;
|
||||
}
|
||||
if (controlBarView != null) {
|
||||
windowManager.removeView(controlBarView);
|
||||
controlBarView = null;
|
||||
}
|
||||
isFloatingViewsShown = false;
|
||||
logDebug("悬浮窗已移除");
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "移除悬浮窗失败", e);
|
||||
isFloatingViewsShown = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void logDebug(String message) {
|
||||
Log.d(TAG, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ public class ForegroundService extends Service {
|
||||
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
|
||||
// 仅在未显示悬浮窗时显示
|
||||
if (floatingViewManager != null && !isFloatingViewShown) {
|
||||
try {
|
||||
floatingViewManager.showFloatingViews();
|
||||
@ -65,10 +64,7 @@ public class ForegroundService extends Service {
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建通知渠道(Android 8.0+)
|
||||
*/
|
||||
|
||||
private void createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(
|
||||
|
||||
@ -8,16 +8,17 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.auto.autoclicker.databinding.ActivityMainBinding;
|
||||
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private Button startButton;
|
||||
private ActivityMainBinding binding;
|
||||
private ActivityResultLauncher<Intent> permissionLauncher;
|
||||
private boolean isFloatingShown = false;
|
||||
private long lastClickTime = 0;
|
||||
@ -26,10 +27,11 @@ public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
startButton = findViewById(R.id.start_Button);
|
||||
startButton.setOnClickListener(v -> toggleFloatingWindow());
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
binding.startButton.setOnClickListener(v -> toggleFloatingWindow());
|
||||
|
||||
permissionLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> checkPermissions());
|
||||
|
||||
@ -75,7 +77,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
startButton.setEnabled(allPermissionsGranted);
|
||||
binding.startButton.setEnabled(allPermissionsGranted);
|
||||
updateButtonText();
|
||||
}
|
||||
|
||||
@ -135,7 +137,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
isFloatingShown = true;
|
||||
Toast.makeText(this, "悬浮窗已显示", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
AutoClickService service = AutoClickService.getInstance();
|
||||
stopService(new Intent(this, ForegroundService.class));
|
||||
service.stopClicking();
|
||||
isFloatingShown = false;
|
||||
Toast.makeText(this, "悬浮窗已隐藏", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@ -143,6 +147,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void updateButtonText() {
|
||||
startButton.setText(isFloatingShown ? R.string.hide_floating_window : R.string.show_floating_window);
|
||||
binding.startButton.setText(isFloatingShown ? R.string.hide_floating_window : R.string.show_floating_window);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.auto.autoclicker;
|
||||
package com.auto.autoclicker.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.auto.autoclicker;
|
||||
package com.auto.autoclicker.util;
|
||||
|
||||
import android.graphics.Point;
|
||||
|
||||
9
app/src/main/res/drawable/cancel.xml
Normal file
9
app/src/main/res/drawable/cancel.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M510.1,475.9L378.4,339.5c-10.4,-10.7 -27.4,-10.9 -38.1,-0.5 -5.2,4.9 -8.2,11.7 -8.3,18.9 -0.2,7.2 2.6,14.1 7.5,19.2l131.7,136.4 -136.4,131.7c-10.7,10.4 -10.9,27.4 -0.5,38.1 4.9,5.2 11.7,8.2 18.9,8.3 7.2,0.2 14.1,-2.6 19.2,-7.5l136.4,-131.7 131.7,136.4c10.4,10.7 27.4,10.9 38.1,0.5 5.2,-4.9 8.2,-11.7 8.3,-18.9 0.2,-7.2 -2.6,-14.1 -7.5,-19.2L547.7,514.8l136.4,-131.7c10.7,-10.4 10.9,-27.4 0.5,-38.1 -4.9,-5.2 -11.7,-8.2 -18.9,-8.3 -7.2,-0.2 -14.1,2.6 -19.2,7.5L510.1,475.9zM220.4,793.2c-155.7,-161.3 -151.2,-418.2 10,-574 161.3,-155.7 418.2,-151.2 574,10 155.7,161.3 151.3,418.2 -10,574 -161.3,155.7 -418.2,151.3 -574,-10zM220.4,793.2"
|
||||
android:fillColor="#333333"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/eye.xml
Normal file
12
app/src/main/res/drawable/eye.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M508,512m-112,0a112,112 0,1 0,224 0,112 112,0 1,0 -224,0Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M942.2,486.2C847.4,286.5 704.1,186 512,186c-192.2,0 -335.4,100.5 -430.2,300.3 -7.7,16.2 -7.7,35.2 0,51.5C176.6,737.5 319.9,838 512,838c192.2,0 335.4,-100.5 430.2,-300.3 7.7,-16.2 7.7,-35 0,-51.5zM508,688c-97.2,0 -176,-78.8 -176,-176s78.8,-176 176,-176 176,78.8 176,176 -78.8,176 -176,176z"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/play.xml
Normal file
12
app/src/main/res/drawable/play.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M512,74.7C270.9,74.7 74.7,270.9 74.7,512S270.9,949.3 512,949.3 949.3,753.1 949.3,512 753.1,74.7 512,74.7zM512,885.3c-204.8,0 -373.3,-168.5 -373.3,-373.3S307.2,138.7 512,138.7 885.3,307.2 885.3,512 716.8,885.3 512,885.3z"
|
||||
android:fillColor="#666666"/>
|
||||
<path
|
||||
android:pathData="M708.3,465.1l-234.7,-134.4c-8.5,-4.3 -17.1,-6.4 -25.6,-6.4 -29.9,0 -53.3,23.5 -53.3,53.3v268.8c0,8.5 2.1,19.2 6.4,25.6 10.7,17.1 27.7,27.7 46.9,27.7 8.5,0 17.1,-2.1 25.6,-6.4l234.7,-134.4c8.5,-4.3 14.9,-10.7 19.2,-19.2 6.4,-12.8 8.5,-27.7 4.3,-40.5 -2.1,-14.9 -10.7,-25.6 -23.5,-34.1zM458.7,627.2L458.7,396.8L661.3,512l-202.7,115.2z"
|
||||
android:fillColor="#666666"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/rounded_background.xml
Normal file
5
app/src/main/res/drawable/rounded_background.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#80000000" /> <!-- 半透明黑色背景 -->
|
||||
<corners android:radius="24dp" /> <!-- 圆角 -->
|
||||
</shape>
|
||||
12
app/src/main/res/drawable/save.xml
Normal file
12
app/src/main/res/drawable/save.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M819.8,83.7L207,83.7c-67.7,0 -122.6,54.9 -122.6,122.6v612.8c0,67.7 54.9,122.6 122.6,122.6h612.8c67.7,0 122.6,-54.9 122.6,-122.6L942.4,206.3c-0,-67.7 -54.9,-122.6 -122.6,-122.6zM695.4,147v241.1L331.8,388.1L331.8,147h363.6zM881.2,819.3c0,33.8 -27.3,61.2 -61.1,61.2L207.1,880.5c-16.4,0 -31.9,-6.3 -43.5,-17.9s-18,-26.9 -18,-43.3v-612.9c0.1,-33.9 27.6,-61.4 61.5,-61.4h61.3v245.3c-0.1,33.8 27.3,61.2 61.1,61.2h367.9c33.9,0 61.3,-27.4 61.3,-61.2L758.7,144.9h61.2c33.9,0 61.3,27.5 61.3,61.4L881.2,819.3z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M574.8,329.9c17.5,0 31.7,-14.2 31.7,-31.7v-61.3c0,-17.5 -14.2,-31.7 -31.7,-31.7s-31.7,14.2 -31.7,31.7v61.3c0,17.5 14.2,31.7 31.7,31.7z"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/setting.xml
Normal file
12
app/src/main/res/drawable/setting.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M509.4,666.1c-83.6,0 -151.5,-67.9 -151.5,-151.5s67.9,-151.5 151.5,-151.5 151.5,67.9 151.5,151.5 -67.9,151.5 -151.5,151.5zM509.4,404.9c-60.6,0 -109.7,49.1 -109.7,109.7s49.1,109.7 109.7,109.7 109.7,-49.1 109.7,-109.7 -49.1,-109.7 -109.7,-109.7z"
|
||||
android:fillColor="#333333"/>
|
||||
<path
|
||||
android:pathData="M556.4,930h-83.6c-47.5,0 -86.2,-38.7 -86.2,-86.2v-23c0,-1 -0.5,-2.1 -1.6,-2.6h-0.5c-1,-0.5 -2.1,0 -3.1,0.5l-14.6,15.2c-16.2,16.2 -37.1,25.1 -59.6,25.1 -22.5,0 -43.4,-8.9 -59,-24.6l-59,-59c-32.4,-32.4 -32.4,-85.2 0,-118.1l15.7,-15.2c1,-1 1,-2.1 0.5,-3.1v-0.5c-0.5,-1 -1.6,-1.6 -2.6,-1.6h-23c-47.5,0 -86.2,-38.7 -86.2,-86.2v-78.4c0.5,-47 39.2,-85.7 86.7,-85.7h21.4c1,0 2.1,-0.5 2.6,-2.1 0.5,-1 1,-2.6 1.6,-3.7 0.5,-1 0,-2.1 -0.5,-3.1l-16.2,-16.7C156.7,329.1 156.7,275.9 189.1,243.5l59,-59c15.7,-15.7 36.6,-24.6 59,-24.6 22.5,0 43.4,8.9 59,24.6l15.2,15.7c0.5,1 2.1,1 3.1,0.5h0.5c1,-0.5 1.6,-1.6 1.6,-2.6v-17.8C386.6,132.7 425.3,94 472.8,94h83.6c44.4,0 81,36.6 81,81v21.4c0,1 0.5,2.1 2.1,2.6 1.6,0.5 2.6,1 3.7,1.6 1,0.5 2.1,0 3.1,-0.5l16.7,-16.2c32.4,-32.4 85.2,-32.4 118.1,0.5l59,59c15.7,15.7 24.6,36.6 24.6,59 0,22.5 -8.9,43.4 -24.6,59l-15.7,16.2c-0.5,0.5 -1,2.1 -0.5,2.6 0.5,1 1,2.6 1.6,3.7 0.5,1 1.6,2.1 2.6,2.1h21.4c44.4,0 81,36.6 81,81v88.8c0,44.4 -36.6,81 -81,81h-23c-1,0 -2.1,0.5 -2.6,1.6 -0.5,1.6 -0.5,2.6 0.5,3.7l15.2,14.6c16.2,16.2 25.1,37.1 24.6,59.6 0,22.5 -8.9,43.4 -24.6,59l-59,59c-15.7,15.7 -36.6,24.6 -59,24.6s-43.4,-8.9 -59,-24.6l-16.2,-15.7c-0.5,-0.5 -2.1,-1 -2.6,-0.5 -1,0.5 -2.6,1 -3.7,1.6 -1,0.5 -2.1,1.6 -2.1,2.6v26.6C637.4,893.4 600.8,930 556.4,930zM402.3,780.5c16.2,7.3 26.1,23 26.1,40.8v23c0,24.6 19.9,44.4 44.4,44.4h83.6c21.4,0 39.2,-17.8 39.2,-39.2v-26.6c0,-18.3 11,-34.5 28.2,-41.3 1,-0.5 1.6,-0.5 2.6,-1 16.7,-7.3 35.5,-3.7 48.6,8.9l16.2,15.7c16.7,16.7 43.4,16.7 59.6,0l59,-59c7.8,-7.8 12,-18.3 12,-29.8 0,-11 -4.2,-21.4 -12,-29.8l-14.6,-14.1c-13.6,-13.1 -17.8,-32.9 -9.9,-50.2v-0.5c6.8,-15.7 23,-26.1 40.8,-26.1h23c21.4,0 39.2,-17.8 39.2,-39.2v-88.8c0,-21.4 -17.8,-39.2 -39.2,-39.2h-21.4c-18.3,0 -34.5,-11 -41.3,-28.2 -0.5,-1 -0.5,-1.6 -1,-2.6 -7.3,-16.7 -3.7,-35.5 8.9,-48.6l15.7,-16.2c7.8,-7.8 12.5,-18.8 12.5,-29.8 0,-11.5 -4.2,-21.9 -12,-29.8L751.3,214.2c-16.2,-16.2 -42.8,-16.2 -59,0l-17.2,16.2c-13.1,12.5 -32.4,15.7 -48.6,8.9 -0.5,-0.5 -1.6,-0.5 -2.6,-1 -17.2,-6.8 -28.2,-23 -28.2,-41.3v-21.4c0,-21.4 -17.8,-39.2 -39.2,-39.2h-83.6c-24.6,0 -44.4,19.9 -44.4,44.4V198.5c0,17.8 -10.4,33.4 -26.6,40.8 -17.2,7.8 -37.1,3.7 -50.2,-9.4l-15.2,-15.7c-7.8,-7.8 -18.3,-12 -29.3,-12 -11,0 -21.4,4.2 -29.3,12L218.9,272.7c-16.2,16.2 -16.2,42.8 0,59l16.2,17.2c12.5,13.1 16.2,32.4 8.9,48.6 -0.5,0.5 -0.5,1.6 -1,2.6 -6.8,17.2 -23,28.2 -41.3,28.2h-21.4c-24.6,0 -44.4,19.9 -44.4,44.4v78.4c0,24.6 19.9,44.4 44.4,44.4h23c17.8,0 33.4,10.4 40.8,26.6v0.5c7.3,16.7 3.7,37.1 -9.4,49.6l-15.7,15.2c-16.2,16.2 -16.2,42.3 0,58.5l59,59c7.8,7.8 18.3,12 29.3,12 11,0 21.4,-4.2 29.8,-12.5l14.1,-14.6c13.1,-13.6 32.9,-17.8 50.2,-9.9l1,0.5z"
|
||||
android:fillColor="#333333"/>
|
||||
</vector>
|
||||
@ -1,16 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#80000000"
|
||||
android:background="@drawable/rounded_background"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/toggle_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/start_click" />
|
||||
<ImageView
|
||||
android:id="@+id/play_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:src="@drawable/play" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/file_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:src="@drawable/save" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/eye_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:src="@drawable/eye" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settings_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:src="@drawable/setting" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/close_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/cancel" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -6,4 +6,10 @@
|
||||
<string name="hide_floating_window">隐藏悬浮窗</string>
|
||||
<string name="start_click">开始点击</string>
|
||||
<string name="stop_click">停止点击</string>
|
||||
<string name="play_button_desc">Play</string>
|
||||
<string name="file_button_desc">File</string>
|
||||
<string name="camera_button_desc">Camera</string>
|
||||
<string name="eye_button_desc">Eye</string>
|
||||
<string name="settings_button_desc">Settings</string>
|
||||
<string name="close_button_desc">Close</string>
|
||||
</resources>
|
||||
Loading…
Reference in New Issue
Block a user