功能添加

This commit is contained in:
lihongwei 2025-06-30 15:24:58 +08:00
parent 5a78b467fc
commit 427f0b12c4
7 changed files with 436 additions and 307 deletions

View File

@ -30,8 +30,6 @@ public class AutoClickService extends AccessibilityService {
private static final long MIN_CLICK_INTERVAL = 40; private static final long MIN_CLICK_INTERVAL = 40;
private static final long MAX_CLICK_INTERVAL = 10000; 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 static final int MIN_SLIDE_DURATION = 100; private static final int MIN_SLIDE_DURATION = 100;
private static final int MAX_SLIDE_DURATION = 2000; private static final int MAX_SLIDE_DURATION = 2000;
@ -109,15 +107,6 @@ public class AutoClickService extends AccessibilityService {
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");
return;
}
this.clickDuration = duration;
logDebug("设置点击时长: " + duration + "ms");
}
public void setSlideDuration(int duration) { public void setSlideDuration(int duration) {
if (duration < MIN_SLIDE_DURATION || duration > MAX_SLIDE_DURATION) { if (duration < MIN_SLIDE_DURATION || duration > MAX_SLIDE_DURATION) {
Log.w(TAG, "滑动时长超出范围: " + duration + "ms"); Log.w(TAG, "滑动时长超出范围: " + duration + "ms");
@ -127,11 +116,6 @@ public class AutoClickService extends AccessibilityService {
logDebug("设置滑动时长: " + duration + "ms"); logDebug("设置滑动时长: " + duration + "ms");
} }
/**
* 设置事件队列的循环次数
*
* @param count 循环次数设置为0表示无限循环设置为1表示不循环执行一次
*/
public void setLoopCount(int count) { public void setLoopCount(int count) {
if (count < 0) { if (count < 0) {
Log.w(TAG, "循环次数不能为负数,已设置为默认值 1"); Log.w(TAG, "循环次数不能为负数,已设置为默认值 1");
@ -140,18 +124,12 @@ public class AutoClickService extends AccessibilityService {
this.loopCount = count; this.loopCount = count;
} }
logDebug("设置循环次数: " + loopCount + ""); logDebug("设置循环次数: " + loopCount + "");
// 如果设置了循环次数则重置循环时间为0确保两种模式不冲突
if (this.loopCount > 0) { if (this.loopCount > 0) {
this.loopTimeMillis = 0; this.loopTimeMillis = 0;
logDebug("已重置循环时间为 0ms"); logDebug("已重置循环时间为 0ms");
} }
} }
/**
* 设置事件队列的循环总时间
*
* @param timeMillis 循环总时间单位毫秒设置为0表示不按时间循环
*/
public void setLoopTime(long timeMillis) { public void setLoopTime(long timeMillis) {
if (timeMillis < 0) { if (timeMillis < 0) {
Log.w(TAG, "循环时间不能为负数,已设置为默认值 0ms"); Log.w(TAG, "循环时间不能为负数,已设置为默认值 0ms");
@ -160,7 +138,6 @@ public class AutoClickService extends AccessibilityService {
this.loopTimeMillis = timeMillis; this.loopTimeMillis = timeMillis;
} }
logDebug("设置循环时间: " + loopTimeMillis + "ms"); logDebug("设置循环时间: " + loopTimeMillis + "ms");
// 如果设置了循环时间则重置循环次数为0确保两种模式不冲突
if (this.loopTimeMillis > 0) { if (this.loopTimeMillis > 0) {
this.loopCount = 0; this.loopCount = 0;
logDebug("已重置循环次数为 0"); logDebug("已重置循环次数为 0");
@ -203,10 +180,9 @@ public class AutoClickService extends AccessibilityService {
EventViewBinder.setAllTouchPointsDraggable(true); EventViewBinder.setAllTouchPointsDraggable(true);
// 重置循环状态 currentEventIndex = 0;
currentEventIndex = 0; // 停止时重置事件索引 currentLoop = 0;
currentLoop = 0; // 停止时重置循环计数 startTimeMillis = 0;
startTimeMillis = 0; // 停止时重置开始时间
logDebug("停止执行事件"); logDebug("停止执行事件");
} }
@ -224,29 +200,26 @@ public class AutoClickService extends AccessibilityService {
if (runtimeEvents.isEmpty()) { if (runtimeEvents.isEmpty()) {
logDebug("跳过执行:事件队列为空"); logDebug("跳过执行:事件队列为空");
stopClicking(); // 如果事件队列为空则停止服务 stopClicking();
return; return;
} }
// 在每一轮循环开始前排序确保顺序正确
runtimeEvents.sort(Comparator.comparingInt(EventWrapper::getOrder)); runtimeEvents.sort(Comparator.comparingInt(EventWrapper::getOrder));
// 检查是否完成了一轮事件列表
if (currentEventIndex >= runtimeEvents.size()) { if (currentEventIndex >= runtimeEvents.size()) {
currentEventIndex = 0; // 重置事件索引准备开始新一轮循环 currentEventIndex = 0;
currentLoop++; // 完成一轮增加循环计数 currentLoop++;
logDebug("完成第 " + currentLoop + " 轮事件执行。"); logDebug("完成第 " + currentLoop + " 轮事件执行。");
// 判断是否继续循环
boolean continueLoop = false; boolean continueLoop = false;
if (loopCount > 0) { // 按次数循环模式 if (loopCount > 0) {
if (currentLoop < loopCount) { if (currentLoop < loopCount) {
continueLoop = true; continueLoop = true;
logDebug("继续第 " + (currentLoop + 1) + " 轮循环 (共 " + loopCount + " 轮)"); logDebug("继续第 " + (currentLoop + 1) + " 轮循环 (共 " + loopCount + " 轮)");
} else { } else {
logDebug("已达到设定的循环次数 (" + loopCount + " 次),停止循环。"); logDebug("已达到设定的循环次数 (" + loopCount + " 次),停止循环。");
} }
} else if (loopTimeMillis > 0) { // 按时间循环模式 } else if (loopTimeMillis > 0) {
long elapsedTime = System.currentTimeMillis() - startTimeMillis; long elapsedTime = System.currentTimeMillis() - startTimeMillis;
if (elapsedTime < loopTimeMillis) { if (elapsedTime < loopTimeMillis) {
continueLoop = true; continueLoop = true;
@ -254,13 +227,13 @@ public class AutoClickService extends AccessibilityService {
} else { } else {
logDebug("已达到设定的循环时间 (" + (loopTimeMillis / 1000) + "s),停止循环。"); logDebug("已达到设定的循环时间 (" + (loopTimeMillis / 1000) + "s),停止循环。");
} }
} else { // 无限循环模式 (loopCount == 0 && loopTimeMillis == 0) } else {
continueLoop = true; continueLoop = true;
logDebug("无限循环模式,继续下一轮循环。"); logDebug("无限循环模式,继续下一轮循环。");
} }
if (!continueLoop) { if (!continueLoop) {
stopClicking(); // 不再继续循环则停止服务 stopClicking();
return; return;
} }
} }
@ -274,8 +247,8 @@ public class AutoClickService extends AccessibilityService {
performSlide((SlideEvent) event); performSlide((SlideEvent) event);
} else { } else {
logDebug("未知或不匹配的事件类型,跳过执行: " + wrapper.getType()); logDebug("未知或不匹配的事件类型,跳过执行: " + wrapper.getType());
currentEventIndex++; // 跳过当前事件 currentEventIndex++;
handler.postDelayed(this::executeEventsByType, clickInterval); // 立即尝试下一个事件 handler.postDelayed(this::executeEventsByType, clickInterval);
} }
} }

View File

@ -4,6 +4,7 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType; import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -12,18 +13,35 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatButton;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.auto.clicker.autoclicker.R; import com.auto.clicker.autoclicker.R;
import com.auto.clicker.autoclicker.databinding.FragmentActionBinding; import com.auto.clicker.autoclicker.databinding.FragmentActionBinding;
import com.auto.clicker.autoclicker.service.AutoClickService;
public class ActionFragment extends Fragment { public class ActionFragment extends Fragment {
private static final String TAG = "ActionFragment";
private FragmentActionBinding binding; private FragmentActionBinding binding;
private static final int TYPE_INTERVAL = 0; private static final int TYPE_INTERVAL = 0;
private static final int TYPE_SWIPE_DURATION = 1; private static final int TYPE_SWIPE_DURATION = 1;
private static final int TYPE_REPEAT = 2; private static final int TYPE_REPEAT = 2;
private enum UnitType {
MS, SEC, MIN, INFINITELY, DURATION, CYCLE, UNKNOWN
}
private UnitType currentIntervalUnit = UnitType.MS;
private UnitType currentSwipeDurationUnit = UnitType.MS;
private UnitType currentRepeatUnit = UnitType.INFINITELY;
private String currentIntervalValue = "";
private String currentDurationValue = "";
private String currentRepeatValue = "";
private boolean isRepeatSwitchChecked = false;
private AppCompatButton saveSettingsButton;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@ -33,38 +51,61 @@ public class ActionFragment extends Fragment {
binding.unitSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_SWIPE_DURATION)); binding.unitSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_SWIPE_DURATION));
setupRepeatMode(); setupRepeatMode();
setupAdvancedMode(); setupAdvancedMode();
restoreUIState();
saveSettingsButton = binding.save;
saveSettingsButton.setOnClickListener(v -> {
applySettingsToService();
Toast.makeText(getContext(), "设置已保存并应用!", Toast.LENGTH_SHORT).show();
});
return binding.getRoot(); return binding.getRoot();
} }
@Override
public void onResume() {
super.onResume();
restoreUIState();
}
private void setupRepeatMode() { private void setupRepeatMode() {
binding.repeatSwitch.setChecked(isRepeatSwitchChecked);
updateRepeatUI(isRepeatSwitchChecked);
binding.repeatSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { binding.repeatSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) { isRepeatSwitchChecked = isChecked;
binding.repeatInput.setVisibility(View.VISIBLE); updateRepeatUI(isChecked);
binding.repeatSelectorContainer.setVisibility(View.VISIBLE); });
binding.repeatSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_REPEAT));
}
private void updateRepeatUI(boolean isChecked) {
if (isChecked) {
binding.repeatInput.setVisibility(View.VISIBLE);
binding.repeatSelectorContainer.setVisibility(View.VISIBLE);
if (currentRepeatUnit == UnitType.INFINITELY) {
binding.repeatSelectedUnit.setText(getString(R.string.infinitely_unit)); binding.repeatSelectedUnit.setText(getString(R.string.infinitely_unit));
binding.etRepeatValue.setText(""); binding.etRepeatValue.setText("");
binding.etRepeatValue.setEnabled(false); binding.etRepeatValue.setEnabled(false);
binding.etRepeatValue.setInputType(InputType.TYPE_NULL); binding.etRepeatValue.setInputType(InputType.TYPE_NULL);
} else { } else if (currentRepeatUnit == UnitType.DURATION) {
binding.repeatInput.setVisibility(View.GONE); binding.repeatSelectedUnit.setText(getString(R.string.duration_unit));
binding.repeatSelectorContainer.setVisibility(View.GONE); binding.etRepeatValue.setText(currentRepeatValue);
binding.etRepeatValue.setEnabled(true);
binding.etRepeatValue.setInputType(InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_TIME);
} else if (currentRepeatUnit == UnitType.CYCLE) {
binding.repeatSelectedUnit.setText(getString(R.string.cycle_unit));
binding.etRepeatValue.setText(currentRepeatValue);
binding.etRepeatValue.setEnabled(true);
binding.etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER);
} }
}); } else {
if (!binding.repeatSwitch.isChecked()) {
binding.repeatInput.setVisibility(View.GONE); binding.repeatInput.setVisibility(View.GONE);
binding.repeatSelectorContainer.setVisibility(View.GONE); binding.repeatSelectorContainer.setVisibility(View.GONE);
} else {
binding.repeatSelectedUnit.setText(getString(R.string.infinitely_unit));
binding.etRepeatValue.setText("");
binding.etRepeatValue.setEnabled(false);
binding.etRepeatValue.setInputType(InputType.TYPE_NULL);
} }
binding.repeatSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_REPEAT));
} }
private void setupAdvancedMode() { private void setupAdvancedMode() {
@ -72,9 +113,9 @@ public class ActionFragment extends Fragment {
binding.advancedSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { binding.advancedSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) { if (isChecked) {
Toast.makeText(getContext(), "Anti-Detection mode is ON", Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "防检测模式已开启", Toast.LENGTH_SHORT).show();
} else { } else {
Toast.makeText(getContext(), "Anti-Detection mode is OFF", Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "防检测模式已关闭", Toast.LENGTH_SHORT).show();
} }
}); });
} }
@ -98,132 +139,251 @@ public class ActionFragment extends Fragment {
TextView tvDuration = popupView.findViewById(R.id.tv_unit_duration); TextView tvDuration = popupView.findViewById(R.id.tv_unit_duration);
TextView tvCycle = popupView.findViewById(R.id.tv_unit_cycle); TextView tvCycle = popupView.findViewById(R.id.tv_unit_cycle);
tvMs.setVisibility(View.GONE);
tvSec.setVisibility(View.GONE);
tvMin.setVisibility(View.GONE);
tvInfinitely.setVisibility(View.GONE);
tvDuration.setVisibility(View.GONE);
tvCycle.setVisibility(View.GONE);
switch (type) { switch (type) {
case TYPE_INTERVAL: case TYPE_INTERVAL:
tvMs.setVisibility(View.VISIBLE); tvMs.setVisibility(View.VISIBLE);
tvSec.setVisibility(View.VISIBLE); tvSec.setVisibility(View.VISIBLE);
tvMin.setVisibility(View.VISIBLE); tvMin.setVisibility(View.VISIBLE);
tvInfinitely.setVisibility(View.GONE);
tvDuration.setVisibility(View.GONE);
tvCycle.setVisibility(View.GONE);
break; break;
case TYPE_SWIPE_DURATION: case TYPE_SWIPE_DURATION:
tvMs.setVisibility(View.VISIBLE); tvMs.setVisibility(View.VISIBLE);
tvSec.setVisibility(View.VISIBLE); tvSec.setVisibility(View.VISIBLE);
tvMin.setVisibility(View.GONE);
tvInfinitely.setVisibility(View.GONE);
tvDuration.setVisibility(View.GONE);
tvCycle.setVisibility(View.GONE);
break; break;
case TYPE_REPEAT: case TYPE_REPEAT:
tvMs.setVisibility(View.GONE);
tvSec.setVisibility(View.GONE);
tvMin.setVisibility(View.GONE);
tvInfinitely.setVisibility(View.VISIBLE); tvInfinitely.setVisibility(View.VISIBLE);
tvDuration.setVisibility(View.VISIBLE); tvDuration.setVisibility(View.VISIBLE);
tvCycle.setVisibility(View.VISIBLE); tvCycle.setVisibility(View.VISIBLE);
break; break;
} }
if (type == TYPE_INTERVAL || type == TYPE_SWIPE_DURATION) { tvMs.setOnClickListener(v -> {
tvMs.setOnClickListener(v -> { UnitType selectedUnitType = UnitType.MS;
String unitText = getString(R.string.milliseconds_unit); String unitText = getString(R.string.milliseconds_unit);
if (type == TYPE_INTERVAL) { updateUIAndSaveSettings(type, selectedUnitType, unitText);
binding.intervalSelectedUnit.setText(unitText); popupWindow.dismiss();
showInputValue("Interval", binding.etIntervalValue.getText().toString(), unitText); });
} else {
binding.tvSelectedUnit.setText(unitText); tvSec.setOnClickListener(v -> {
showInputValue("Swipe Duration", binding.etDurationValue.getText().toString(), unitText); UnitType selectedUnitType = UnitType.SEC;
} String unitText = getString(R.string.seconds_unit);
updateUIAndSaveSettings(type, selectedUnitType, unitText);
popupWindow.dismiss();
});
if (type == TYPE_INTERVAL) {
tvMin.setOnClickListener(v -> {
UnitType selectedUnitType = UnitType.MIN;
String unitText = getString(R.string.minutes_unit);
updateUIAndSaveSettings(type, selectedUnitType, unitText);
popupWindow.dismiss(); popupWindow.dismiss();
}); });
tvSec.setOnClickListener(v -> {
String unitText = getString(R.string.seconds_unit);
if (type == TYPE_INTERVAL) {
binding.intervalSelectedUnit.setText(unitText);
showInputValue("Interval", binding.etIntervalValue.getText().toString(), unitText);
} else {
binding.tvSelectedUnit.setText(unitText);
showInputValue("Swipe Duration", binding.etDurationValue.getText().toString(), unitText);
}
popupWindow.dismiss();
});
if (type == TYPE_INTERVAL) {
tvMin.setOnClickListener(v -> {
String unitText = getString(R.string.minutes_unit);
binding.intervalSelectedUnit.setText(unitText);
popupWindow.dismiss();
showInputValue("Interval", binding.etIntervalValue.getText().toString(), unitText);
});
}
} }
if (type == TYPE_REPEAT) { if (type == TYPE_REPEAT) {
tvInfinitely.setOnClickListener(v -> { tvInfinitely.setOnClickListener(v -> {
binding.repeatSelectedUnit.setText(getString(R.string.infinitely_unit)); UnitType selectedUnitType = UnitType.INFINITELY;
binding.etRepeatValue.setText(""); String unitText = getString(R.string.infinitely_unit);
binding.etRepeatValue.setEnabled(false); updateUIAndSaveSettings(type, selectedUnitType, unitText);
binding.etRepeatValue.setInputType(InputType.TYPE_NULL); updateRepeatUI(true);
popupWindow.dismiss(); popupWindow.dismiss();
showInputValue("Repeat", binding.etRepeatValue.getText().toString(), getString(R.string.infinitely_unit));
}); });
tvDuration.setOnClickListener(v -> { tvDuration.setOnClickListener(v -> {
binding.repeatSelectedUnit.setText(getString(R.string.duration_unit)); UnitType selectedUnitType = UnitType.DURATION;
binding.etRepeatValue.setText(""); String unitText = getString(R.string.duration_unit);
binding.etRepeatValue.setEnabled(true); updateUIAndSaveSettings(type, selectedUnitType, unitText);
binding.etRepeatValue.setInputType(InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_TIME); // 设置为时间格式 updateRepeatUI(true);
popupWindow.dismiss(); popupWindow.dismiss();
showInputValue("Repeat", binding.etRepeatValue.getText().toString(), getString(R.string.duration_unit));
}); });
tvCycle.setOnClickListener(v -> { tvCycle.setOnClickListener(v -> {
binding.repeatSelectedUnit.setText(getString(R.string.cycle_unit)); UnitType selectedUnitType = UnitType.CYCLE;
binding.etRepeatValue.setText(""); String unitText = getString(R.string.cycle_unit);
binding.etRepeatValue.setEnabled(true); updateUIAndSaveSettings(type, selectedUnitType, unitText);
binding.etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER); updateRepeatUI(true);
popupWindow.dismiss(); popupWindow.dismiss();
showInputValue("Repeat", binding.etRepeatValue.getText().toString(), getString(R.string.cycle_unit));
}); });
} }
popupWindow.showAsDropDown(anchorView); popupWindow.showAsDropDown(anchorView);
} }
private void showInputValue(String type, String value, String unit) { private void updateUIAndSaveSettings(int type, UnitType selectedUnitType, String unitText) {
String message = type + " 值: " + (value.isEmpty() ? "未输入" : value) + ", 单位: " + unit; switch (type) {
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show(); case TYPE_INTERVAL:
binding.intervalSelectedUnit.setText(unitText);
currentIntervalUnit = selectedUnitType;
break;
case TYPE_SWIPE_DURATION:
binding.tvSelectedUnit.setText(unitText);
currentSwipeDurationUnit = selectedUnitType;
break;
case TYPE_REPEAT:
binding.repeatSelectedUnit.setText(unitText);
currentRepeatUnit = selectedUnitType;
break;
}
saveCurrentInputValues();
showInputValue(type, getEditTextValue(type), unitText);
}
if (type.equals("Interval")) { private String getEditTextValue(int type) {
long intervalValue = value.isEmpty() ? 0 : Long.parseLong(value); switch (type) {
// 根据 unit 进行单位转换或保存 Interval case TYPE_INTERVAL: return binding.etIntervalValue.getText().toString();
// 例如if (unit.equals(getString(R.string.seconds_unit))) { ... } case TYPE_SWIPE_DURATION: return binding.etDurationValue.getText().toString();
} else if (type.equals("Swipe Duration")) { case TYPE_REPEAT: return binding.etRepeatValue.getText().toString();
long durationValue = value.isEmpty() ? 0 : Long.parseLong(value); default: return "";
// 根据 unit 进行单位转换或保存 Swipe Duration }
} else if (type.equals("Repeat")) { }
if (unit.equals(getString(R.string.infinitely_unit))) {
// Repeat 为无限次不需要处理输入值 private void showInputValue(int type, String value, String unitText) {
} else if (unit.equals(getString(R.string.duration_unit))) { String typeName = "";
// Repeat 为时长处理时间格式的输入 switch (type) {
// 您需要在这里添加解析时间格式的逻辑 case TYPE_INTERVAL: typeName = "点击间隔"; break;
String durationValue = value.isEmpty() ? "0" : value; case TYPE_SWIPE_DURATION: typeName = "滑动时长"; break;
// long parsedDuration = parseDurationString(durationValue); // 自定义方法解析时间 case TYPE_REPEAT: typeName = "循环模式"; break;
Toast.makeText(getContext(), "Repeat Duration: " + durationValue, Toast.LENGTH_SHORT).show(); }
} else if (unit.equals(getString(R.string.cycle_unit))) { String message = typeName + " 值: " + (value.isEmpty() ? "未输入" : value) + ", 单位: " + unitText;
// Repeat 为次数处理整数输入 Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
int repeatCount = value.isEmpty() ? 0 : Integer.parseInt(value); }
Toast.makeText(getContext(), "Repeat Cycles: " + repeatCount, Toast.LENGTH_SHORT).show();
private void saveCurrentInputValues() {
currentIntervalValue = binding.etIntervalValue.getText().toString();
currentDurationValue = binding.etDurationValue.getText().toString();
currentRepeatValue = binding.etRepeatValue.getText().toString();
isRepeatSwitchChecked = binding.repeatSwitch.isChecked();
}
private void restoreUIState() {
binding.etIntervalValue.setText(currentIntervalValue);
binding.intervalSelectedUnit.setText(getUnitString(currentIntervalUnit));
binding.etDurationValue.setText(currentDurationValue);
binding.tvSelectedUnit.setText(getUnitString(currentSwipeDurationUnit));
binding.repeatSwitch.setChecked(isRepeatSwitchChecked);
updateRepeatUI(isRepeatSwitchChecked);
if (isRepeatSwitchChecked) {
binding.repeatSelectedUnit.setText(getUnitString(currentRepeatUnit));
}
}
private String getUnitString(UnitType unitType) {
switch (unitType) {
case MS: return getString(R.string.milliseconds_unit);
case SEC: return getString(R.string.seconds_unit);
case MIN: return getString(R.string.minutes_unit);
case INFINITELY: return getString(R.string.infinitely_unit);
case DURATION: return getString(R.string.duration_unit);
case CYCLE: return getString(R.string.cycle_unit);
default: return "";
}
}
public void applySettingsToService() {
saveCurrentInputValues();
AutoClickService service = AutoClickService.getInstance();
if (service == null) {
Toast.makeText(getContext(), "自动点击服务未运行,无法应用设置。", Toast.LENGTH_SHORT).show();
Log.e(TAG, "AutoClickService 实例为空,无法应用设置。");
return;
}
long intervalValue = 0;
if (!currentIntervalValue.isEmpty()) {
try {
intervalValue = Long.parseLong(currentIntervalValue);
if (currentIntervalUnit == UnitType.SEC) {
intervalValue *= 1000;
} else if (currentIntervalUnit == UnitType.MIN) {
intervalValue *= 60 * 1000;
}
service.setClickInterval(intervalValue);
Log.d(TAG, "应用点击间隔到服务: " + intervalValue + "ms");
} catch (NumberFormatException e) {
Log.e(TAG, "点击间隔值解析错误: " + currentIntervalValue, e);
Toast.makeText(getContext(), "点击间隔值无效,请输入有效数字。", Toast.LENGTH_SHORT).show();
} }
} else {
Log.d(TAG, "点击间隔值为空,未应用到服务。");
}
long slideDurationValue = 0;
if (!currentDurationValue.isEmpty()) {
try {
slideDurationValue = Long.parseLong(currentDurationValue);
if (currentSwipeDurationUnit == UnitType.SEC) {
slideDurationValue *= 1000;
}
service.setSlideDuration((int) slideDurationValue);
Log.d(TAG, "应用滑动时长到服务: " + slideDurationValue + "ms");
} catch (NumberFormatException e) {
Log.e(TAG, "滑动时长值解析错误: " + currentDurationValue, e);
Toast.makeText(getContext(), "滑动时长值无效,请输入有效数字。", Toast.LENGTH_SHORT).show();
}
} else {
Log.d(TAG, "滑动时长值为空,未应用到服务。");
}
if (isRepeatSwitchChecked) {
if (currentRepeatUnit == UnitType.INFINITELY) {
service.setLoopCount(0);
Log.d(TAG, "应用重复模式: 无限次。");
} else if (currentRepeatUnit == UnitType.DURATION) {
long repeatDurationMillis = 0;
if (!currentRepeatValue.isEmpty()) {
try {
repeatDurationMillis = Long.parseLong(currentRepeatValue);
service.setLoopTime(repeatDurationMillis);
Log.d(TAG, "应用重复时长: " + repeatDurationMillis + "ms。");
} catch (NumberFormatException e) {
Log.e(TAG, "重复时长值解析错误: " + currentRepeatValue, e);
Toast.makeText(getContext(), "重复时长值无效,请输入有效数字或正确的时间格式。", Toast.LENGTH_SHORT).show();
service.setLoopTime(0);
}
} else {
service.setLoopTime(0);
Log.d(TAG, "重复时长值为空,取消时间循环。");
}
service.setLoopCount(0);
} else if (currentRepeatUnit == UnitType.CYCLE) {
int repeatCount = 0;
if (!currentRepeatValue.isEmpty()) {
try {
repeatCount = Integer.parseInt(currentRepeatValue);
service.setLoopCount(repeatCount);
Log.d(TAG, "应用重复次数: " + repeatCount + "次。");
} catch (NumberFormatException e) {
Log.e(TAG, "重复次数值解析错误: " + currentRepeatValue, e);
Toast.makeText(getContext(), "重复次数值无效,请输入有效数字。", Toast.LENGTH_SHORT).show();
service.setLoopCount(1);
}
} else {
service.setLoopCount(1);
Log.d(TAG, "重复次数值为空,设置为执行一次。");
}
service.setLoopTime(0);
}
} else {
service.setLoopCount(1);
service.setLoopTime(0);
Log.d(TAG, "重复开关关闭,服务设置为执行一次。");
} }
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
saveCurrentInputValues();
binding = null; binding = null;
} }
} }

View File

@ -22,14 +22,12 @@ import java.util.Map;
public class EventViewBinder { public class EventViewBinder {
// 存储每个视图及其对应的 OnTouchListener 实例用于启用/禁用拖动
private static final Map<View, View.OnTouchListener> activeDragListeners = new HashMap<>(); private static final Map<View, View.OnTouchListener> activeDragListeners = new HashMap<>();
public interface OnPositionChangedCallback { public interface OnPositionChangedCallback {
void onPositionChanged(int x, int y); void onPositionChanged(int x, int y);
} }
// --- bindPoint 方法 ---
public static void bindPoint(Context context, WindowManager windowManager, public static void bindPoint(Context context, WindowManager windowManager,
PointEvent pointEvent, int touchPointSize, PointEvent pointEvent, int touchPointSize,
int screenWidth, int screenHeight, int screenWidth, int screenHeight,
@ -47,7 +45,6 @@ public class EventViewBinder {
pointView.setTextSize(TypedValue.COMPLEX_UNIT_SP, initialTextSize); pointView.setTextSize(TypedValue.COMPLEX_UNIT_SP, initialTextSize);
// 创建并保存 OnTouchListener
View.OnTouchListener touchListener = createTouchListener( View.OnTouchListener touchListener = createTouchListener(
pointView, params, windowManager, screenWidth, screenHeight, pointView, params, windowManager, screenWidth, screenHeight,
(x, y) -> { (x, y) -> {
@ -57,12 +54,11 @@ public class EventViewBinder {
}); });
pointView.setOnTouchListener(touchListener); pointView.setOnTouchListener(touchListener);
activeDragListeners.put(pointView, touchListener); // 保存监听器到 Map activeDragListeners.put(pointView, touchListener);
windowManager.addView(pointView, params); windowManager.addView(pointView, params);
} }
// --- bindSlide 方法 ---
public static void bindSlide(Context context, WindowManager windowManager, public static void bindSlide(Context context, WindowManager windowManager,
SlideEvent slideEvent, int touchPointSize, SlideEvent slideEvent, int touchPointSize,
int screenWidth, int screenHeight, int screenWidth, int screenHeight,
@ -126,15 +122,13 @@ public class EventViewBinder {
updateLinePosition(slideEvent, touchPointSize); updateLinePosition(slideEvent, touchPointSize);
} }
// --- DraggableHelper 移动过来的 OnTouchListener 创建逻辑 ---
// 这个方法创建并返回一个 View.OnTouchListener 实例
private static View.OnTouchListener createTouchListener( private static View.OnTouchListener createTouchListener(
View view, WindowManager.LayoutParams params, WindowManager windowManager, View view, WindowManager.LayoutParams params, WindowManager windowManager,
int screenWidth, int screenHeight, DraggableHelper.DragCallback callback) { // 仍然使用 DraggableHelper.DragCallback 接口 int screenWidth, int screenHeight, DraggableHelper.DragCallback callback) {
return new View.OnTouchListener() { return new View.OnTouchListener() {
private float lastX, lastY; private float lastX, lastY;
private float paramX, paramY; private float paramX, paramY;
private boolean isDragging = false; // 标记是否正在拖动 private boolean isDragging = false;
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
@ -144,7 +138,7 @@ public class EventViewBinder {
lastY = event.getRawY(); lastY = event.getRawY();
paramX = params.x; paramX = params.x;
paramY = params.y; paramY = params.y;
isDragging = false; // 重置拖动状态 isDragging = false;
return true; return true;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
@ -169,7 +163,7 @@ public class EventViewBinder {
return true; return true;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
if (!isDragging) { // 如果没有拖动才视为点击 if (!isDragging) {
v.performClick(); v.performClick();
} }
return true; return true;
@ -179,42 +173,25 @@ public class EventViewBinder {
}; };
} }
// --- 新增方法统一控制所有触摸点的拖动状态 ---
public static void setAllTouchPointsDraggable(boolean draggable) { public static void setAllTouchPointsDraggable(boolean draggable) {
for (Map.Entry<View, View.OnTouchListener> entry : activeDragListeners.entrySet()) { for (Map.Entry<View, View.OnTouchListener> entry : activeDragListeners.entrySet()) {
View view = entry.getKey(); View view = entry.getKey();
View.OnTouchListener listener = entry.getValue(); View.OnTouchListener listener = entry.getValue();
if (draggable) { if (draggable) {
// 启用拖动重新设置保存的监听器
view.setOnTouchListener(listener); view.setOnTouchListener(listener);
} else { } else {
// 禁用拖动将监听器设置为 null阻止触摸事件
view.setOnTouchListener(null); view.setOnTouchListener(null);
} }
} }
} }
// --- 新增方法移除不再需要的视图及其监听器 ---
public static void removeBoundView(WindowManager windowManager, View view) {
if (view != null) {
try {
windowManager.removeView(view);
activeDragListeners.remove(view); // Map 中移除
Log.d("EventViewBinder", "移除视图并清理监听器: " + view.getTag());
} catch (IllegalArgumentException e) {
Log.e("EventViewBinder", "尝试移除不存在的视图: " + e.getMessage());
}
}
}
// --- 辅助方法 (保持不变) ---
public static TextView createTouchPointView(Context context, String label) { public static TextView createTouchPointView(Context context, String label) {
TextView touchPointView = new TextView(context); TextView touchPointView = new TextView(context);
touchPointView.setBackgroundResource(R.drawable.ring_has_bg); touchPointView.setBackgroundResource(R.drawable.ring_has_bg);
touchPointView.setGravity(Gravity.CENTER); touchPointView.setGravity(Gravity.CENTER);
touchPointView.setText(label); touchPointView.setText(label);
touchPointView.setTextColor(Color.WHITE); touchPointView.setTextColor(Color.WHITE);
touchPointView.setTag(label); // 添加一个Tag方便日志识别 touchPointView.setTag(label);
return touchPointView; return touchPointView;
} }
@ -245,7 +222,7 @@ public class EventViewBinder {
overlayType, overlayType,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, // 线条通常不可触摸 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT PixelFormat.TRANSLUCENT
); );
params.gravity = Gravity.TOP | Gravity.START; params.gravity = Gravity.TOP | Gravity.START;

View File

@ -96,7 +96,6 @@ public class FloatingSettingDialogManager {
unitSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_SWIPE_DURATION)); unitSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_SWIPE_DURATION));
setupRepeatMode(); setupRepeatMode();
// --- 恢复UI状态 ---
restoreUIState(); restoreUIState();
// floatingDialogView.setOnTouchListener((v, event) -> { // floatingDialogView.setOnTouchListener((v, event) -> {
@ -179,8 +178,8 @@ public class FloatingSettingDialogManager {
overlayType, overlayType,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL // 允许将触摸事件传递到其下方窗口 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, // 监听外部触摸事件 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT PixelFormat.TRANSLUCENT
); );
params.gravity = Gravity.CENTER; params.gravity = Gravity.CENTER;
@ -195,7 +194,7 @@ public class FloatingSettingDialogManager {
} }
repeatSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { repeatSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
isRepeatSwitchChecked = isChecked; // 保存开关状态 isRepeatSwitchChecked = isChecked;
updateRepeatUI(isChecked); updateRepeatUI(isChecked);
}); });
@ -206,16 +205,14 @@ public class FloatingSettingDialogManager {
if (isChecked) { if (isChecked) {
repeatInput.setVisibility(View.VISIBLE); repeatInput.setVisibility(View.VISIBLE);
repeatSelectorContainer.setVisibility(View.VISIBLE); repeatSelectorContainer.setVisibility(View.VISIBLE);
// 只有当单位是无限次时才禁用输入框
if (currentRepeatUnit.equals(context.getString(R.string.infinitely_unit)) || repeatSelectedUnit.getText().toString().equals(context.getString(R.string.infinitely_unit))) { if (currentRepeatUnit.equals(context.getString(R.string.infinitely_unit)) || repeatSelectedUnit.getText().toString().equals(context.getString(R.string.infinitely_unit))) {
etRepeatValue.setText(""); etRepeatValue.setText("");
etRepeatValue.setEnabled(false); etRepeatValue.setEnabled(false);
etRepeatValue.setInputType(InputType.TYPE_NULL); etRepeatValue.setInputType(InputType.TYPE_NULL);
repeatSelectedUnit.setText(context.getString(R.string.infinitely_unit)); // 确保显示无限次 repeatSelectedUnit.setText(context.getString(R.string.infinitely_unit));
} else { } else {
etRepeatValue.setEnabled(true); etRepeatValue.setEnabled(true);
etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER); // 默认设置为数字输入 etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER);
// 恢复之前的输入值和单位
etRepeatValue.setText(currentRepeatValue); etRepeatValue.setText(currentRepeatValue);
repeatSelectedUnit.setText(currentRepeatUnit.isEmpty() ? context.getString(R.string.cycle_unit) : currentRepeatUnit); repeatSelectedUnit.setText(currentRepeatUnit.isEmpty() ? context.getString(R.string.cycle_unit) : currentRepeatUnit);
} }
@ -383,8 +380,6 @@ public class FloatingSettingDialogManager {
showToastOnUi(context, "点击间隔值无效,请输入有效数字。"); showToastOnUi(context, "点击间隔值无效,请输入有效数字。");
} }
} else { } else {
// 如果为空设置一个默认值或不设置这取决于你的业务逻辑
// service.setClickInterval(默认值);
Log.d(TAG, "点击间隔值为空,未应用到服务。"); Log.d(TAG, "点击间隔值为空,未应用到服务。");
} }
@ -402,12 +397,9 @@ public class FloatingSettingDialogManager {
showToastOnUi(context, "滑动时长值无效,请输入有效数字。"); showToastOnUi(context, "滑动时长值无效,请输入有效数字。");
} }
} else { } else {
// 如果为空设置一个默认值或不设置
// service.setSlideDuration(默认值);
Log.d(TAG, "滑动时长值为空,未应用到服务。"); Log.d(TAG, "滑动时长值为空,未应用到服务。");
} }
// 应用重复设置
if (isRepeatSwitchChecked) { if (isRepeatSwitchChecked) {
if (currentRepeatUnit.equals(context.getString(R.string.infinitely_unit))) { if (currentRepeatUnit.equals(context.getString(R.string.infinitely_unit))) {
service.setLoopCount(0); // 无限循环 service.setLoopCount(0); // 无限循环
@ -417,8 +409,6 @@ public class FloatingSettingDialogManager {
if (!currentRepeatValue.isEmpty()) { if (!currentRepeatValue.isEmpty()) {
try { try {
repeatDurationMillis = Long.parseLong(currentRepeatValue); repeatDurationMillis = Long.parseLong(currentRepeatValue);
// 根据你的UI单位这里可能需要进一步转换例如用户输入的是秒
// repeatDurationMillis *= 1000L;
service.setLoopTime(repeatDurationMillis); service.setLoopTime(repeatDurationMillis);
Log.d(TAG, "应用重复时长: " + repeatDurationMillis + "ms。"); Log.d(TAG, "应用重复时长: " + repeatDurationMillis + "ms。");
} catch (NumberFormatException e) { } catch (NumberFormatException e) {

View File

@ -24,7 +24,6 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.auto.clicker.autoclicker.R; import com.auto.clicker.autoclicker.R;
@ -87,6 +86,13 @@ public class FloatingViewManager {
private static final int DEFAULT_CONTROL_BAR_WIDTH_DP = 50; private static final int DEFAULT_CONTROL_BAR_WIDTH_DP = 50;
private ImageView playButton; private ImageView playButton;
private ImageView addButton;
private ImageView removeButton;
private ImageView slideButton;
private ImageView saveButton;
private ImageView eyeButton;
private ImageView settingButton;
private ImageView closeButton;
public FloatingViewManager(Context context) { public FloatingViewManager(Context context) {
this.context = context; this.context = context;
@ -145,7 +151,7 @@ public class FloatingViewManager {
multipleControlBarParams.height = WindowManager.LayoutParams.WRAP_CONTENT; multipleControlBarParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
setupDraggableView(multipleControlBarView, multipleControlBarParams, this::updateMoreControlBarPosition); setupDraggableView(multipleControlBarView, multipleControlBarParams, this::updateMoreControlBarPosition);
setupControlButtons(multipleControlBarView,mode); setupControlButtons(multipleControlBarView, mode);
updateControlBarImageViews(multipleControlBarView, this.controlBarWidth); updateControlBarImageViews(multipleControlBarView, this.controlBarWidth);
} }
@ -223,17 +229,17 @@ public class FloatingViewManager {
windowManager.updateViewLayout(multipleControlBarView, multipleControlBarParams); windowManager.updateViewLayout(multipleControlBarView, multipleControlBarParams);
} }
private void setupControlButtons(LinearLayout controlBar,int mode) { private void setupControlButtons(LinearLayout controlBar, int mode) {
playButton = controlBar.findViewById(R.id.play_button); playButton = controlBar.findViewById(R.id.play_button);
ImageView addButton = controlBar.findViewById(R.id.add_button); addButton = controlBar.findViewById(R.id.add_button);
ImageView removeButton = controlBar.findViewById(R.id.remove_button); removeButton = controlBar.findViewById(R.id.remove_button);
ImageView slideButton = controlBar.findViewById(R.id.slide_button); slideButton = controlBar.findViewById(R.id.slide_button);
ImageView saveButton = controlBar.findViewById(R.id.save_button); saveButton = controlBar.findViewById(R.id.save_button);
ImageView eyeButton = controlBar.findViewById(R.id.eye_button); eyeButton = controlBar.findViewById(R.id.eye_button);
ImageView settingButton = controlBar.findViewById(R.id.settings_button); settingButton = controlBar.findViewById(R.id.settings_button);
ImageView closeButton = controlBar.findViewById(R.id.close_button); closeButton = controlBar.findViewById(R.id.close_button);
if (mode == 1){ if (mode == 1) {
addButton.setVisibility(View.GONE); addButton.setVisibility(View.GONE);
removeButton.setVisibility(View.GONE); removeButton.setVisibility(View.GONE);
slideButton.setVisibility(View.GONE); slideButton.setVisibility(View.GONE);
@ -336,59 +342,90 @@ public class FloatingViewManager {
public void toggleEventsVisibility(boolean show) { public void toggleEventsVisibility(boolean show) {
for (EventWrapper wrapper : new ArrayList<>(runtimeEvents)) { for (EventWrapper wrapper : new ArrayList<>(runtimeEvents)) {
// 获取事件的视图 WindowManager.LayoutParams params = null;
View viewToToggle = null;
if (wrapper.getType() == EventWrapper.EventType.POINT) { if (wrapper.getType() == EventWrapper.EventType.POINT) {
viewToToggle = EventViewBinder.createTouchPointView(context, String.valueOf(wrapper.getEvent().getId())); PointEvent pointEvent = (PointEvent) wrapper.getEvent();
View pointView = pointEvent.getView();
if (pointView != null) {
params = (WindowManager.LayoutParams) pointView.getLayoutParams();
if (params != null) {
if (show) {
pointView.setAlpha(1.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
} else {
pointView.setAlpha(0.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
windowManager.updateViewLayout(pointView, params);
}
}
} else if (wrapper.getType() == EventWrapper.EventType.SLIDE) { } else if (wrapper.getType() == EventWrapper.EventType.SLIDE) {
View startPointView = getView(show, wrapper, context); SlideEvent slideEvent = (SlideEvent) wrapper.getEvent();
WindowManager.LayoutParams startParams = (WindowManager.LayoutParams) startPointView.getLayoutParams(); View startPointView = slideEvent.getStartPoint().getView();
if (show) { if (startPointView != null) {
startParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; params = (WindowManager.LayoutParams) startPointView.getLayoutParams();
} else { if (params != null) {
startParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; if (show) {
startPointView.setAlpha(1.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
} else {
startPointView.setAlpha(0.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
windowManager.updateViewLayout(startPointView, params);
}
} }
windowManager.updateViewLayout(startPointView, startParams);
continue;
}
if (viewToToggle != null) { View endPointView = slideEvent.getEndPoint().getView();
if (show) { if (endPointView != null) {
viewToToggle.setAlpha(1.0f); params = (WindowManager.LayoutParams) endPointView.getLayoutParams();
} else { if (params != null) {
viewToToggle.setAlpha(0.0f); if (show) {
endPointView.setAlpha(1.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
} else {
endPointView.setAlpha(0.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
windowManager.updateViewLayout(endPointView, params);
}
} }
WindowManager.LayoutParams params = (WindowManager.LayoutParams) viewToToggle.getLayoutParams();
if (show) { View lineView = slideEvent.getLineView();
params.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; if (lineView != null) {
} else { params = (WindowManager.LayoutParams) lineView.getLayoutParams();
params.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; if (params != null) {
if (show) {
lineView.setAlpha(1.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
} else {
lineView.setAlpha(0.0f);
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
windowManager.updateViewLayout(lineView, params);
}
} }
windowManager.updateViewLayout(viewToToggle, params);
} }
} }
} }
@NonNull
private View getView(boolean show, EventWrapper wrapper, Context context) {
SlideEvent slideEvent = (SlideEvent) wrapper.getEvent();
View startPointView = EventViewBinder.createTouchPointView(context, String.valueOf(slideEvent.getStartPoint().getId()));
View endPointView = EventViewBinder.createTouchPointView(context, String.valueOf(slideEvent.getEndPoint().getId()));
View lineView = new ConnectingLineView(context);
if (show) {
startPointView.setAlpha(1.0f);
endPointView.setAlpha(1.0f);
lineView.setAlpha(1.0f);
} else {
startPointView.setAlpha(0.0f);
endPointView.setAlpha(0.0f);
lineView.setAlpha(0.0f);
}
return startPointView;
}
private void removeLastEvent() { private void removeLastEvent() {
if (isMultipleRunning) { if (isMultipleRunning) {
Toast.makeText(context, "请先停止点击", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "请先停止点击", Toast.LENGTH_SHORT).show();
@ -433,6 +470,8 @@ public class FloatingViewManager {
Toast.makeText(context, "多点点击开始", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "多点点击开始", Toast.LENGTH_SHORT).show();
updateTouchPointsBackground(R.drawable.touch_point); updateTouchPointsBackground(R.drawable.touch_point);
setControlButtonsEnabled(false);
} }
private void stopMultiClicking(AutoClickService service) { private void stopMultiClicking(AutoClickService service) {
@ -440,6 +479,25 @@ public class FloatingViewManager {
Toast.makeText(context, "多点点击停止", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "多点点击停止", Toast.LENGTH_SHORT).show();
updateTouchPointsBackground(R.drawable.ring_has_bg); updateTouchPointsBackground(R.drawable.ring_has_bg);
setControlButtonsEnabled(true);
}
private void setControlButtonsEnabled(boolean enabled) {
if (addButton != null) addButton.setEnabled(enabled);
if (removeButton != null) removeButton.setEnabled(enabled);
if (slideButton != null) slideButton.setEnabled(enabled);
if (saveButton != null) saveButton.setEnabled(enabled);
if (eyeButton != null) eyeButton.setEnabled(enabled);
if (settingButton != null) settingButton.setEnabled(enabled);
float alpha = enabled ? 1.0f : 0.5f;
if (addButton != null) addButton.setAlpha(alpha);
if (removeButton != null) removeButton.setAlpha(alpha);
if (slideButton != null) slideButton.setAlpha(alpha);
if (saveButton != null) saveButton.setAlpha(alpha);
if (eyeButton != null) eyeButton.setAlpha(alpha);
if (settingButton != null) settingButton.setAlpha(alpha);
} }
private void removeEvent(Event event) { private void removeEvent(Event event) {
@ -606,7 +664,7 @@ public class FloatingViewManager {
return; return;
} }
Solution newSolution = new Solution(solutionName,mode); Solution newSolution = new Solution(solutionName, mode);
eventRepository.insertSolutionWithEvents(newSolution, runtimeEvents, new EventRepository.RepositoryCallback<Long>() { eventRepository.insertSolutionWithEvents(newSolution, runtimeEvents, new EventRepository.RepositoryCallback<Long>() {
@Override @Override
public void onComplete(Long solutionId) { public void onComplete(Long solutionId) {
@ -782,7 +840,7 @@ public class FloatingViewManager {
} }
if (slideEvent.getEndPoint().getView() != null && slideEvent.getEndPoint().getLayoutParams() != null) { if (slideEvent.getEndPoint().getView() != null && slideEvent.getEndPoint().getLayoutParams() != null) {
TextView endView = slideEvent.getEndPoint().getView(); TextView endView = slideEvent.getEndPoint().getView();
WindowManager.LayoutParams endParams = slideEvent.getEndPoint().getLayoutParams(); WindowManager.LayoutParams endParams = slideEvent.getEndPoint().getLayoutParams();
endParams.width = touchPointSize; endParams.width = touchPointSize;
endParams.height = touchPointSize; endParams.height = touchPointSize;

View File

@ -14,11 +14,12 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/default_actions_container" android:id="@+id/default_actions_container"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="223dp" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_marginTop="14dp" android:layout_marginTop="14dp"
android:layout_marginEnd="20dp" android:layout_marginEnd="20dp"
android:background="@drawable/bg_rounded_rect" android:background="@drawable/bg_rounded_rect"
android:paddingBottom="10dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
@ -112,6 +113,18 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/tv_interval_range_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:layout_marginTop="4dp"
android:text="范围: 40ms - 10000ms"
android:textColor="@color/gray"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/input_interval" />
<ImageView <ImageView
android:id="@+id/duration_icon" android:id="@+id/duration_icon"
android:layout_width="20dp" android:layout_width="20dp"
@ -130,7 +143,7 @@
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/tv_interval_label" app:layout_constraintStart_toStartOf="@+id/tv_interval_label"
app:layout_constraintTop_toBottomOf="@id/input_interval" /> app:layout_constraintTop_toBottomOf="@id/tv_interval_range_hint" />
<TextView <TextView
android:id="@+id/tv_preview_label" android:id="@+id/tv_preview_label"
@ -140,6 +153,7 @@
android:text="@string/preview" android:text="@string/preview"
android:textColor="@color/blue" android:textColor="@color/blue"
android:textSize="12sp" android:textSize="12sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/tv_swipe_duration_label" app:layout_constraintBottom_toBottomOf="@id/tv_swipe_duration_label"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_swipe_duration_label" /> app:layout_constraintTop_toTopOf="@id/tv_swipe_duration_label" />
@ -199,6 +213,17 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/tv_duration_range_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:layout_marginTop="4dp"
android:text="范围: 100ms - 2000ms"
android:textColor="@color/gray"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/input_with_unit_container" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
@ -375,6 +400,20 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/save"
android:layout_width="150dp"
android:layout_height="54dp"
android:layout_marginTop="18dp"
android:background="@drawable/btn_border_background"
android:backgroundTint="#0BC4FC"
android:text="Save"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="21sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/default_advanced_container" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="38dp"
android:layout_height="wrap_content"
android:background="@drawable/control_bar_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingHorizontal="10dp">
<ImageView
android:id="@+id/play_button"
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="16dp"
android:src="@drawable/play" />
<ImageView
android:id="@+id/save_button"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginBottom="16dp"
android:src="@drawable/save" />
<ImageView
android:id="@+id/eye_button"
android:layout_width="16dp"
android:layout_height="9dp"
android:layout_marginBottom="16dp"
android:src="@drawable/eye" />
<ImageView
android:id="@+id/settings_button"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginBottom="9dp"
android:src="@drawable/control_setting" />
</LinearLayout>
<ImageView
android:id="@+id/cut_off"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="10dp"
android:scaleType="fitXY"
android:src="@drawable/cut_off_line" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingHorizontal="10dp">
<ImageView
android:id="@+id/close_button"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginBottom="11dp"
android:src="@drawable/cancel" />
</LinearLayout>
</LinearLayout>