diff --git a/app/src/main/java/com/auto/clicker/autoclicker/service/ForegroundService.java b/app/src/main/java/com/auto/clicker/autoclicker/service/ForegroundService.java index 520c614..fe659a0 100644 --- a/app/src/main/java/com/auto/clicker/autoclicker/service/ForegroundService.java +++ b/app/src/main/java/com/auto/clicker/autoclicker/service/ForegroundService.java @@ -24,11 +24,16 @@ public class ForegroundService extends Service { private static final int NOTIFICATION_ID = 1; private FloatingViewManager floatingViewManager; private boolean isFloatingViewShown = false; + private static ForegroundService instance; @Override public void onCreate() { super.onCreate(); + + instance = this; + createNotificationChannel(); + try { floatingViewManager = new FloatingViewManager(this); } catch (Exception e) { @@ -68,6 +73,14 @@ public class ForegroundService extends Service { return START_STICKY; } + public static ForegroundService getInstance() { + return instance; + } + + public FloatingViewManager getFloatingViewManager() { + return floatingViewManager; + } + private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( @@ -86,6 +99,9 @@ public class ForegroundService extends Service { @Override public void onDestroy() { super.onDestroy(); + + instance = null; + if (floatingViewManager != null) { floatingViewManager.removeAllFloatingViews(); isFloatingViewShown = false; diff --git a/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/ActionFragment.java b/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/ActionFragment.java index e9e7348..48d5a42 100644 --- a/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/ActionFragment.java +++ b/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/ActionFragment.java @@ -1,20 +1,137 @@ package com.auto.clicker.autoclicker.ui.fragment.setting; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.PopupWindow; +import android.widget.TextView; +import android.widget.Toast; import androidx.fragment.app.Fragment; import com.auto.clicker.autoclicker.R; +import com.auto.clicker.autoclicker.databinding.FragmentActionBinding; public class ActionFragment extends Fragment { - + private FragmentActionBinding binding; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_action, container, false); + binding = FragmentActionBinding.inflate(inflater, container, false); + + binding.intervalSelectorContainer.setOnClickListener(this::showIntervalUnitSelection); + + binding.unitSelectorContainer.setOnClickListener(this::showSwipeDurationUnitSelection); + + return binding.getRoot(); + } + + private void showIntervalUnitSelection(View anchorView) { + // 加载弹窗布局 + View popupView = getLayoutInflater().inflate(R.layout.dialog_unit_selection, null); + PopupWindow popupWindow = new PopupWindow( + popupView, + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + true // 设置为 true,以便点击外部区域时自动关闭 + ); + + // 设置背景,否则点击外部无法关闭 + popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + popupWindow.setOutsideTouchable(true); + + // 获取弹窗中的TextViews + TextView tvMs = popupView.findViewById(R.id.tv_unit_ms); + TextView tvSec = popupView.findViewById(R.id.tv_unit_sec); + TextView tvMin = popupView.findViewById(R.id.tv_unit_min); + + // Interval 单位有:毫秒,秒,分钟 + tvMs.setVisibility(View.VISIBLE); + tvSec.setVisibility(View.VISIBLE); + tvMin.setVisibility(View.VISIBLE); + + tvMs.setOnClickListener(v -> { + binding.intervalSelectedUnit.setText(getString(R.string.milliseconds_unit)); + popupWindow.dismiss(); + showInputValue("Interval", binding.etIntervalValue.getText().toString(), getString(R.string.milliseconds_unit)); + }); + + tvSec.setOnClickListener(v -> { + binding.intervalSelectedUnit.setText(getString(R.string.seconds_unit)); + popupWindow.dismiss(); + showInputValue("Interval", binding.etIntervalValue.getText().toString(), getString(R.string.seconds_unit)); + }); + + tvMin.setOnClickListener(v -> { + binding.intervalSelectedUnit.setText(getString(R.string.minutes_unit)); + popupWindow.dismiss(); + showInputValue("Interval", binding.etIntervalValue.getText().toString(), getString(R.string.minutes_unit)); + }); + + // 显示弹窗,使其显示在anchorView下方 + popupWindow.showAsDropDown(anchorView); + } + + private void showSwipeDurationUnitSelection(View anchorView) { + // 加载弹窗布局 + View popupView = getLayoutInflater().inflate(R.layout.dialog_unit_selection, null); + PopupWindow popupWindow = new PopupWindow( + popupView, + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + true // 设置为 true,以便点击外部区域时自动关闭 + ); + + // 设置背景,否则点击外部无法关闭 + popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + popupWindow.setOutsideTouchable(true); + + // 获取弹窗中的TextViews + TextView tvMs = popupView.findViewById(R.id.tv_unit_ms); + TextView tvSec = popupView.findViewById(R.id.tv_unit_sec); + TextView tvMin = popupView.findViewById(R.id.tv_unit_min); + + // Swipe duration 单位只有:毫秒,秒 + tvMs.setVisibility(View.VISIBLE); + tvSec.setVisibility(View.VISIBLE); + tvMin.setVisibility(View.GONE); // 隐藏分钟选项 + + tvMs.setOnClickListener(v -> { + binding.tvSelectedUnit.setText(getString(R.string.milliseconds_unit)); + popupWindow.dismiss(); + showInputValue("Swipe Duration", binding.etDurationValue.getText().toString(), getString(R.string.milliseconds_unit)); + }); + + tvSec.setOnClickListener(v -> { + binding.tvSelectedUnit.setText(getString(R.string.seconds_unit)); + popupWindow.dismiss(); + showInputValue("Swipe Duration", binding.etDurationValue.getText().toString(), getString(R.string.seconds_unit)); + }); + + // 显示弹窗,使其显示在anchorView下方 + popupWindow.showAsDropDown(anchorView); + } + + private void showInputValue(String type, String value, String unit) { + String message = type + " 值: " + (value.isEmpty() ? "未输入" : value) + ", 单位: " + unit; + Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show(); + + if (type.equals("Interval")) { + long intervalValue = value.isEmpty() ? 0 : Long.parseLong(value); + // 根据 unit 进行单位转换或保存 + } else if (type.equals("Swipe Duration")) { + long durationValue = value.isEmpty() ? 0 : Long.parseLong(value); + // 根据 unit 进行单位转换或保存 + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; } } \ No newline at end of file diff --git a/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/UISizeFragment.java b/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/UISizeFragment.java index bafd485..bf98384 100644 --- a/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/UISizeFragment.java +++ b/app/src/main/java/com/auto/clicker/autoclicker/ui/fragment/setting/UISizeFragment.java @@ -1,20 +1,166 @@ package com.auto.clicker.autoclicker.ui.fragment.setting; import android.os.Bundle; +import android.util.Log; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.SeekBar; +import android.widget.Toast; import androidx.fragment.app.Fragment; -import com.auto.clicker.autoclicker.R; +import com.auto.clicker.autoclicker.databinding.FragmentUISizeBinding; +import com.auto.clicker.autoclicker.service.ForegroundService; +import com.auto.clicker.autoclicker.view.FloatingViewManager; public class UISizeFragment extends Fragment { + private static final String TAG = "UISizeFragment"; + private FragmentUISizeBinding binding; + private FloatingViewManager floatingViewManager; + + private static final int MIN_POINT_SIZE = 50; + private static final int MAX_POINT_SIZE = 200; + + private static final int MIN_CONTROL_BAR_WIDTH_DP = 20; + private static final int MAX_CONTROL_BAR_WIDTH_DP = 80; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_u_i_size, container, false); + binding = FragmentUISizeBinding.inflate(inflater, container, false); + + ForegroundService service = ForegroundService.getInstance(); + if (service != null) { + floatingViewManager = service.getFloatingViewManager(); + } + + if (floatingViewManager != null) { + setupPointSizeControl(); + setupControlBarSizeControl(); + } else { + Toast.makeText(getContext(), "自动化服务未运行,UI大小设置功能不可用。", Toast.LENGTH_LONG).show(); + disableAllControlUI(); + } + + return binding.getRoot(); + } + + private void setupPointSizeControl() { + binding.pointSeekbar.setMax(MAX_POINT_SIZE - MIN_POINT_SIZE); + + int currentPointSize = floatingViewManager.getTouchPointSize(); + + currentPointSize = Math.max(MIN_POINT_SIZE, Math.min(MAX_POINT_SIZE, currentPointSize)); + binding.pointSeekbar.setProgress(currentPointSize - MIN_POINT_SIZE); + + updatePointSizeUI(currentPointSize); + + binding.pointSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + int newSize = progress + MIN_POINT_SIZE; + updatePointSizeUI(newSize); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + int finalSize = seekBar.getProgress() + MIN_POINT_SIZE; + floatingViewManager.setTouchPointSize(finalSize); + Log.d(TAG, "触摸点大小设置为: " + finalSize + "px"); + Toast.makeText(getContext(), "触摸点大小已更新", Toast.LENGTH_SHORT).show(); + } + }); + } + + private void setupControlBarSizeControl() { + int minControlBarWidthPx = dpToPx(MIN_CONTROL_BAR_WIDTH_DP); + int maxControlBarWidthPx = dpToPx(MAX_CONTROL_BAR_WIDTH_DP); + + binding.barSeekbar.setMax(maxControlBarWidthPx - minControlBarWidthPx); + + int currentBarWidthPx = floatingViewManager.getControlBarWidth(); + + currentBarWidthPx = Math.max(minControlBarWidthPx, Math.min(maxControlBarWidthPx, currentBarWidthPx)); + binding.barSeekbar.setProgress(currentBarWidthPx - minControlBarWidthPx); + + binding.currentBarSizeText.setText(String.valueOf(pxToDp(currentBarWidthPx)) + "dp"); + + binding.barSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + int newWidthPx = progress + minControlBarWidthPx; + binding.currentBarSizeText.setText(String.valueOf(pxToDp(newWidthPx)) + "dp"); + updateControlBarPreview(newWidthPx); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + int finalWidthPx = seekBar.getProgress() + minControlBarWidthPx; + floatingViewManager.setControlBarSize(finalWidthPx); + Log.d(TAG, "控制栏大小设置为: " + pxToDp(finalWidthPx) + "dp (" + finalWidthPx + "px)"); + Toast.makeText(getContext(), "控制栏大小已更新", Toast.LENGTH_SHORT).show(); + } + }); + } + + private int dpToPx(int dp) { + if (getContext() == null) return dp; + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics()); + } + + private int pxToDp(int px) { + if (getContext() == null) return px; + return (int) (px / getContext().getResources().getDisplayMetrics().density); + } + + private void updatePointSizeUI(int size) { + binding.currentPointSizeText.setText(String.valueOf(size) + "px"); + + ViewGroup.LayoutParams params = binding.ringPreview.getLayoutParams(); + params.width = size; + params.height = size; + binding.ringPreview.setLayoutParams(params); + + float textSize = (float) size / (MAX_POINT_SIZE / 19f); + binding.ringText.setTextSize(textSize); + } + + private void updateControlBarPreview(int width) { + ViewGroup.LayoutParams params = binding.controlBar.getLayoutParams(); + params.width = width; + + params.height = (int) (width * (249f / 37f)); + binding.controlBar.setLayoutParams(params); + } + + private void disableAllControlUI() { + disablePointSizeControlUI(); + binding.barSeekbar.setEnabled(false); + binding.barSizeContainer.setAlpha(0.5f); + } + + private void disablePointSizeControlUI() { + binding.pointSeekbar.setEnabled(false); + binding.currentPointSizeText.setText("N/A"); + binding.ringPreview.setVisibility(View.GONE); + binding.ringText.setVisibility(View.GONE); + binding.pointSizeContainer.setAlpha(0.5f); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; } } \ No newline at end of file diff --git a/app/src/main/java/com/auto/clicker/autoclicker/util/EventViewBinder.java b/app/src/main/java/com/auto/clicker/autoclicker/util/EventViewBinder.java index b01f899..267d997 100644 --- a/app/src/main/java/com/auto/clicker/autoclicker/util/EventViewBinder.java +++ b/app/src/main/java/com/auto/clicker/autoclicker/util/EventViewBinder.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.PixelFormat; import android.os.Build; import android.util.Log; +import android.util.TypedValue; import android.view.Gravity; import android.view.WindowManager; import android.widget.TextView; @@ -23,7 +24,7 @@ public class EventViewBinder { public static void bindPoint(Context context, WindowManager windowManager, PointEvent pointEvent, int touchPointSize, int screenWidth, int screenHeight, - OnPositionChangedCallback callback,int order) { + OnPositionChangedCallback callback,int order,float initialTextSize) { TextView pointView = createTouchPointView(context, String.valueOf(order)); Log.d("bind","id: " + order); @@ -35,6 +36,8 @@ public class EventViewBinder { pointEvent.setView(pointView); pointEvent.setLayoutParams(params); + pointView.setTextSize(TypedValue.COMPLEX_UNIT_SP, initialTextSize); + DraggableHelper.makeDraggable(pointView, params, windowManager, screenWidth, screenHeight, (x, y) -> { @@ -49,7 +52,7 @@ public class EventViewBinder { public static void bindSlide(Context context, WindowManager windowManager, SlideEvent slideEvent, int touchPointSize, int screenWidth, int screenHeight, - OnPositionChangedCallback callback,int order) { + OnPositionChangedCallback callback,int order,float initialTextSize) { PointEvent start = slideEvent.getStartPoint(); PointEvent end = slideEvent.getEndPoint(); @@ -69,6 +72,9 @@ public class EventViewBinder { end.setView(endView); end.setLayoutParams(endParams); + startView.setTextSize(TypedValue.COMPLEX_UNIT_SP, initialTextSize); + endView.setTextSize(TypedValue.COMPLEX_UNIT_SP, initialTextSize); + ConnectingLineView lineView = new ConnectingLineView(context); WindowManager.LayoutParams lineParams = createLineViewParams(context); @@ -108,7 +114,6 @@ public class EventViewBinder { touchPointView.setGravity(Gravity.CENTER); touchPointView.setText(label); touchPointView.setTextColor(Color.WHITE); - touchPointView.setTextSize(19); return touchPointView; } @@ -148,7 +153,7 @@ public class EventViewBinder { return params; } - private static void updateLinePosition(SlideEvent slideEvent, int touchPointSize) { + public static void updateLinePosition(SlideEvent slideEvent, int touchPointSize) { PointEvent start = slideEvent.getStartPoint(); PointEvent end = slideEvent.getEndPoint(); ConnectingLineView lineView = slideEvent.getLineView(); diff --git a/app/src/main/java/com/auto/clicker/autoclicker/view/FloatingViewManager.java b/app/src/main/java/com/auto/clicker/autoclicker/view/FloatingViewManager.java index d642c97..44c49a8 100644 --- a/app/src/main/java/com/auto/clicker/autoclicker/view/FloatingViewManager.java +++ b/app/src/main/java/com/auto/clicker/autoclicker/view/FloatingViewManager.java @@ -5,6 +5,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.graphics.PixelFormat; import android.graphics.Point; import android.os.Build; @@ -13,15 +14,18 @@ import android.os.Looper; import android.provider.Settings; import android.text.InputType; import android.util.Log; +import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -52,7 +56,10 @@ import java.util.List; public class FloatingViewManager { private static final String TAG = "FloatingViewManager"; public static final long DEBOUNCE_INTERVAL = 500; - public static final int TOUCH_POINT_SIZE = 100; + + private int touchPointSize; + + private int controlBarWidth; private final Context context; private final WindowManager windowManager; @@ -74,6 +81,13 @@ public class FloatingViewManager { private final EventRepository eventRepository; + private static final String PREFS_NAME = "AutoClickerPrefs"; + private static final String KEY_TOUCH_POINT_SIZE = "touch_point_size"; + private static final String KEY_CONTROL_BAR_WIDTH = "control_bar_width"; + + private static final int DEFAULT_TOUCH_POINT_SIZE = 100; + private static final int DEFAULT_CONTROL_BAR_WIDTH_DP = 38; + public FloatingViewManager(Context context) { this.context = context; this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); @@ -83,6 +97,10 @@ public class FloatingViewManager { this.floatingTabDialogManager = new FloatingTabDialogManager(context); this.floatingTabDialogManager.setFloatingViewManager(this); this.eventRepository = new EventRepository(context.getApplicationContext()); + this.touchPointSize = 100; + + loadSettings(); + registerBroadcastReceiver(); } @@ -112,16 +130,24 @@ public class FloatingViewManager { } private void initMultipleControlBar() { + if (multipleControlBarView != null) { + safeRemoveView(multipleControlBarView); + multipleControlBarView = null; + } + multipleControlBarView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.multiple_control_bar, null); multipleControlBarParams = createControlBarParams(); - setupDraggableView(multipleControlBarView, multipleControlBarParams, this::updateMoreControlBarPosition); + multipleControlBarParams.width = this.controlBarWidth; + multipleControlBarParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + setupDraggableView(multipleControlBarView, multipleControlBarParams, this::updateMoreControlBarPosition); setupControlButtons(multipleControlBarView); + + updateControlBarImageViews(multipleControlBarView, this.controlBarWidth); } private WindowManager.LayoutParams createControlBarParams() { - // 创建控制栏的悬浮窗参数 int overlayType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE; @@ -257,12 +283,14 @@ public class FloatingViewManager { return; } - PointEvent pointEvent = new PointEvent(eventOrderCounter, screenWidth / 2 - TOUCH_POINT_SIZE / 2, - screenHeight / 2 - TOUCH_POINT_SIZE / 2); + PointEvent pointEvent = new PointEvent(eventOrderCounter, screenWidth / 2 - touchPointSize / 2, + screenHeight / 2 - touchPointSize / 2); + + float currentTextSize = calculateTextSizeForPointSize(this.touchPointSize); EventViewBinder.bindPoint(context, windowManager, pointEvent, - TOUCH_POINT_SIZE, screenWidth, screenHeight, - (x, y) -> updateServicePositions(), eventOrderCounter); + this.touchPointSize, screenWidth, screenHeight, + (x, y) -> updateServicePositions(), eventOrderCounter, currentTextSize); runtimeEvents.add(new EventWrapper(EventWrapper.EventType.POINT, pointEvent, eventOrderCounter)); eventOrderCounter++; @@ -278,9 +306,11 @@ public class FloatingViewManager { PointEvent endPoint = new PointEvent(eventOrderCounter, screenWidth / 2 + 100, screenHeight / 2 - 50); SlideEvent slideEvent = new SlideEvent(eventOrderCounter, startPoint, endPoint); + float currentTextSize = calculateTextSizeForPointSize(this.touchPointSize); + EventViewBinder.bindSlide(context, windowManager, slideEvent, - TOUCH_POINT_SIZE, screenWidth, screenHeight, - (x, y) -> updateServicePositions(), eventOrderCounter); + this.touchPointSize, screenWidth, screenHeight, + (x, y) -> updateServicePositions(), eventOrderCounter, currentTextSize); runtimeEvents.add(new EventWrapper(EventWrapper.EventType.SLIDE, slideEvent, eventOrderCounter)); eventOrderCounter++; @@ -649,11 +679,13 @@ public class FloatingViewManager { if (clickPoint != null) { PointEvent pointEvent = new PointEvent(eventEntity.orderInSolution, clickPoint.x, clickPoint.y); + float currentTextSize = calculateTextSizeForPointSize(FloatingViewManager.this.touchPointSize); + EventViewBinder.bindPoint(context, windowManager, pointEvent, - TOUCH_POINT_SIZE, + FloatingViewManager.this.touchPointSize, screenWidth, screenHeight, - (x, y) -> updateServicePositions(), eventEntity.orderInSolution); + (x, y) -> updateServicePositions(), eventEntity.orderInSolution, currentTextSize); runtimeEvents.add(new EventWrapper(type, pointEvent, pointEvent.getId())); } @@ -667,11 +699,13 @@ public class FloatingViewManager { SlideEvent slideEvent = new SlideEvent(eventEntity.orderInSolution, startPointEvent, endPointEvent); + float currentTextSize = calculateTextSizeForPointSize(FloatingViewManager.this.touchPointSize); + EventViewBinder.bindSlide(context, windowManager, slideEvent, - TOUCH_POINT_SIZE, + FloatingViewManager.this.touchPointSize, screenWidth, screenHeight, - (x, y) -> updateServicePositions(), eventEntity.orderInSolution); + (x, y) -> updateServicePositions(), eventEntity.orderInSolution, currentTextSize); runtimeEvents.add(new EventWrapper(type, slideEvent, slideEvent.getId())); } @@ -715,4 +749,202 @@ public class FloatingViewManager { lastToggleTime = currentTime; return false; } + + private void loadSettings() { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + this.touchPointSize = prefs.getInt(KEY_TOUCH_POINT_SIZE, DEFAULT_TOUCH_POINT_SIZE); + + + int defaultControlBarWidthPx = dpToPx(DEFAULT_CONTROL_BAR_WIDTH_DP); + this.controlBarWidth = prefs.getInt(KEY_CONTROL_BAR_WIDTH, defaultControlBarWidthPx); + + Log.d(TAG, "设置已加载:触摸点大小=" + this.touchPointSize + ", 控制栏宽度=" + this.controlBarWidth); + } + + public void setTouchPointSize(int newSize) { + if (this.touchPointSize == newSize || newSize <= 0) { + return; + } + this.touchPointSize = newSize; + saveTouchPointSize(newSize); + + for (EventWrapper wrapper : new ArrayList<>(runtimeEvents)) { + if (wrapper.getType() == EventWrapper.EventType.POINT) { + PointEvent pe = (PointEvent) wrapper.getEvent(); + updatePointViewSize(pe); + } else if (wrapper.getType() == EventWrapper.EventType.SLIDE) { + SlideEvent se = (SlideEvent) wrapper.getEvent(); + updateSlideViewSize(se); + } + } + } + + private void updatePointViewSize(PointEvent pointEvent) { + if (pointEvent.getView() != null && pointEvent.getLayoutParams() != null) { + TextView pointView = pointEvent.getView(); + WindowManager.LayoutParams params = pointEvent.getLayoutParams(); + + params.width = touchPointSize; + params.height = touchPointSize; + + float newTextSize = calculateTextSizeForPointSize(touchPointSize); + + pointView.setTextSize(TypedValue.COMPLEX_UNIT_SP, newTextSize); + + try { + windowManager.updateViewLayout(pointView, params); + } catch (IllegalArgumentException e) { + Log.w(TAG, "尝试更新不存在的点击点视图", e); + } + } + } + + private void updateSlideViewSize(SlideEvent slideEvent) { + float newTextSize = calculateTextSizeForPointSize(touchPointSize); // 调用新方法计算 + + if (slideEvent.getStartPoint().getView() != null && slideEvent.getStartPoint().getLayoutParams() != null) { + TextView startView = slideEvent.getStartPoint().getView(); + WindowManager.LayoutParams startParams = slideEvent.getStartPoint().getLayoutParams(); + startParams.width = touchPointSize; + startParams.height = touchPointSize; + startView.setTextSize(TypedValue.COMPLEX_UNIT_SP, newTextSize); + try { + windowManager.updateViewLayout(startView, startParams); + } catch (IllegalArgumentException e) { + Log.w(TAG, "尝试更新不存在的滑动起点视图", e); + } + } + + if (slideEvent.getEndPoint().getView() != null && slideEvent.getEndPoint().getLayoutParams() != null) { + TextView endView = slideEvent.getEndPoint().getView(); + WindowManager.LayoutParams endParams = slideEvent.getEndPoint().getLayoutParams(); + endParams.width = touchPointSize; + endParams.height = touchPointSize; + endView.setTextSize(TypedValue.COMPLEX_UNIT_SP, newTextSize); + try { + windowManager.updateViewLayout(endView, endParams); + } catch (IllegalArgumentException e) { + Log.w(TAG, "尝试更新不存在的滑动终点视图", e); + } + } + + EventViewBinder.updateLinePosition(slideEvent, touchPointSize); + } + + private float calculateTextSizeForPointSize(int pointSize) { + final int MIN_POINT_SIZE_FOR_CALC = 50; + final int MAX_POINT_SIZE_FOR_CALC = 200; + final float MIN_TEXT_SIZE_SP = 10f; + final float MAX_TEXT_SIZE_SP = 30f; + + float ratio = (float) (pointSize - MIN_POINT_SIZE_FOR_CALC) / (MAX_POINT_SIZE_FOR_CALC - MIN_POINT_SIZE_FOR_CALC); + return MIN_TEXT_SIZE_SP + (MAX_TEXT_SIZE_SP - MIN_TEXT_SIZE_SP) * ratio; + } + + private void saveTouchPointSize(int size) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + prefs.edit().putInt(KEY_TOUCH_POINT_SIZE, size).apply(); + Log.d(TAG, "触摸点大小已保存: " + size); + } + + private void saveControlBarWidth(int width) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + prefs.edit().putInt(KEY_CONTROL_BAR_WIDTH, width).apply(); + Log.d(TAG, "控制栏宽度已保存: " + width); + } + + public int getTouchPointSize() { + return this.touchPointSize; + } + + private void updateControlBarImageViews(ViewGroup parentView, int newBarWidthPx) { + float scaleFactor = (float) newBarWidthPx / dpToPx(DEFAULT_CONTROL_BAR_WIDTH_DP); + + for (int i = 0; i < parentView.getChildCount(); i++) { + View child = parentView.getChildAt(i); + if (child instanceof ViewGroup) { + // 递归处理嵌套的 ViewGroup + updateControlBarImageViews((ViewGroup) child, newBarWidthPx); + } else if (child instanceof ImageView) { + ImageView imageView = (ImageView) child; + ViewGroup.LayoutParams params = imageView.getLayoutParams(); + + if (imageView.getId() == R.id.cut_off) { + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.height = dpToPx(1); + + imageView.setLayoutParams(params); + continue; + } + + int originalImgWidthDp = 0; + int originalImgHeightDp = 0; + + if (imageView.getId() == R.id.play_button || imageView.getId() == R.id.add_button || imageView.getId() == R.id.remove_button || imageView.getId() == R.id.close_button) { + originalImgWidthDp = 13; + if (imageView.getId() == R.id.remove_button) { + originalImgHeightDp = 2; + } else { + originalImgHeightDp = 13; + } + } else if (imageView.getId() == R.id.slide_button) { + originalImgWidthDp = 17; + originalImgHeightDp = 17; + } else if (imageView.getId() == R.id.save_button) { + originalImgWidthDp = 15; + originalImgHeightDp = 15; + } else if (imageView.getId() == R.id.eye_button) { + originalImgWidthDp = 16; + originalImgHeightDp = 9; + } else if (imageView.getId() == R.id.settings_button) { + originalImgWidthDp = 14; + originalImgHeightDp = 14; + } + + if (originalImgWidthDp > 0) { + // 根据原始 dp 值和缩放因子计算新的像素尺寸 + params.width = (int) (dpToPx(originalImgWidthDp) * scaleFactor); + params.height = (int) (dpToPx(originalImgHeightDp) * scaleFactor); + imageView.setLayoutParams(params); + } else { + if (params.width > 0) { + params.width = (int) (dpToPx(params.width) * scaleFactor); + } + if (params.height > 0) { + params.height = (int) (dpToPx(params.height) * scaleFactor); + } + imageView.setLayoutParams(params); + } + } + } + } + + private int dpToPx(int dp) { + if (context == null) return dp; + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); + } + + public void setControlBarSize(int newWidth) { + if (this.controlBarWidth == newWidth || newWidth <= 0) { + return; + } + this.controlBarWidth = newWidth; + saveControlBarWidth(newWidth); + + if (multipleControlBarView != null && multipleControlBarParams != null) { + multipleControlBarParams.width = this.controlBarWidth; + multipleControlBarParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + + try { + windowManager.updateViewLayout(multipleControlBarView, multipleControlBarParams); + updateControlBarImageViews(multipleControlBarView, this.controlBarWidth); + } catch (IllegalArgumentException e) { + Log.w(TAG, "尝试更新不存在的控制栏视图", e); + } + } + } + + public int getControlBarWidth() { + return controlBarWidth; + } } \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_unit_selection.xml b/app/src/main/res/layout/dialog_unit_selection.xml new file mode 100644 index 0000000..3b59649 --- /dev/null +++ b/app/src/main/res/layout/dialog_unit_selection.xml @@ -0,0 +1,45 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_u_i_size.xml b/app/src/main/res/layout/fragment_u_i_size.xml index a6618c4..0112ec4 100644 --- a/app/src/main/res/layout/fragment_u_i_size.xml +++ b/app/src/main/res/layout/fragment_u_i_size.xml @@ -1,9 +1,9 @@ - - - - - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="100px" /> + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/multiple_control_bar.xml b/app/src/main/res/layout/multiple_control_bar.xml index 85780cb..a1cbe98 100644 --- a/app/src/main/res/layout/multiple_control_bar.xml +++ b/app/src/main/res/layout/multiple_control_bar.xml @@ -9,8 +9,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" - android:orientation="vertical" - android:paddingHorizontal="10dp"> + android:orientation="vertical"> Hello blank fragment Preview This service enables auto-clicking on the screen. - + milliseconds + seconds + minutes \ No newline at end of file