功能添加

This commit is contained in:
lihongwei 2025-06-26 17:59:36 +08:00
parent 0c81561074
commit d021cdc9a9
7 changed files with 731 additions and 66 deletions

View File

@ -364,6 +364,12 @@ public class MainActivity extends AppCompatActivity {
binding.single.setEnabled(isFloatingShown == FLOATING_NONE);
binding.multi.setEnabled(isFloatingShown == FLOATING_NONE);
if (isFloatingShown == FLOATING_NONE) {
setVideo(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.bolangblue));
} else {
setVideo(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.bolangred));
}
}
private void setStartButtonEnabled(boolean enabled) {

View File

@ -17,7 +17,6 @@ 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;

View File

@ -0,0 +1,410 @@
package com.auto.clicker.autoclicker.view;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.InputType;
import android.util.Log;
import android.view.ContextThemeWrapper;
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.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.widget.SwitchCompat;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.auto.clicker.autoclicker.R;
import com.auto.clicker.autoclicker.service.AutoClickService;
public class FloatingSettingDialogManager {
private static final String TAG = "FloatingSettingDialogManager";
private final Context context;
private final WindowManager windowManager;
private ConstraintLayout floatingDialogView;
private WindowManager.LayoutParams floatingDialogParams;
private FloatingViewManager floatingViewManager;
private static final int TYPE_INTERVAL = 0;
private static final int TYPE_SWIPE_DURATION = 1;
private static final int TYPE_REPEAT = 2;
private LinearLayout intervalSelectorContainer;
private LinearLayout unitSelectorContainer;
private SwitchCompat repeatSwitch;
private LinearLayout repeatInput;
private LinearLayout repeatSelectorContainer;
private EditText etIntervalValue;
private TextView intervalSelectedUnit;
private EditText etDurationValue;
private TextView tvSelectedUnit;
private EditText etRepeatValue;
private TextView repeatSelectedUnit;
public FloatingSettingDialogManager(Context context) {
this.context = context;
this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
public void setFloatingViewManager(FloatingViewManager manager) {
this.floatingViewManager = manager;
}
public void showFloatingTabDialog() {
if (floatingDialogView != null) {
removeFloatingTabDialog();
}
Context themedContext = new ContextThemeWrapper(context, R.style.Theme_AutoClicker);
floatingDialogView = (ConstraintLayout) LayoutInflater.from(themedContext).inflate(R.layout.floating_setting_dialog, null);
floatingDialogParams = createFloatingDialogParams();
intervalSelectorContainer = floatingDialogView.findViewById(R.id.dialog_interval_selector_container);
unitSelectorContainer = floatingDialogView.findViewById(R.id.dialog_unit_selector_container);
repeatSwitch = floatingDialogView.findViewById(R.id.dialog_repeat_switch);
repeatInput = floatingDialogView.findViewById(R.id.dialog_repeat_input);
repeatSelectorContainer = floatingDialogView.findViewById(R.id.dialog_repeat_selector_container);
etIntervalValue = floatingDialogView.findViewById(R.id.dialog_et_interval_value);
intervalSelectedUnit = floatingDialogView.findViewById(R.id.dialog_interval_selected_unit);
etDurationValue = floatingDialogView.findViewById(R.id.dialog_et_duration_value);
tvSelectedUnit = floatingDialogView.findViewById(R.id.dialog_tv_selected_unit);
etRepeatValue = floatingDialogView.findViewById(R.id.dialog_et_repeat_value);
repeatSelectedUnit = floatingDialogView.findViewById(R.id.dialog_repeat_selected_unit);
intervalSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_INTERVAL));
unitSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_SWIPE_DURATION));
setupRepeatMode();
floatingDialogView.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
// 如果是外部点击事件就关闭对话框
removeFloatingTabDialog();
Log.d(TAG, "检测到外部点击,浮动标签页弹窗已关闭。");
return true; // 消费此事件
}
return false; // 其他事件不处理
});
try {
windowManager.addView(floatingDialogView, floatingDialogParams);
Log.d(TAG, "浮动标签页弹窗已显示");
} catch (WindowManager.BadTokenException e) {
Log.e(TAG, "无法添加浮动标签页弹窗,可能是权限问题或上下文无效", e);
showToastOnUi(context, "显示弹窗失败,请检查权限。");
} catch (SecurityException e) {
Log.e(TAG, "需要悬浮窗权限才能显示浮动弹窗", e);
showToastOnUi(context, "请授予悬浮窗权限以便显示。");
}
}
public void removeFloatingTabDialog() {
if (floatingDialogView != null) {
try {
windowManager.removeView(floatingDialogView);
floatingDialogView = null;
intervalSelectorContainer = null;
unitSelectorContainer = null;
repeatSwitch = null;
repeatInput = null;
repeatSelectorContainer = null;
etIntervalValue = null;
intervalSelectedUnit = null;
etDurationValue = null;
tvSelectedUnit = null;
etRepeatValue = null;
repeatSelectedUnit = null;
Log.d(TAG, "浮动标签页弹窗已移除");
} catch (IllegalArgumentException e) {
Log.w(TAG, "尝试移除不存在的视图", e);
}
}
}
private WindowManager.LayoutParams createFloatingDialogParams() {
int overlayType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
WindowManager.LayoutParams.TYPE_PHONE;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
overlayType,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL // 允许将触摸事件传递到其下方窗口
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, // 监听外部触摸事件
PixelFormat.TRANSLUCENT
);
params.gravity = Gravity.CENTER;
return params;
}
private void setupRepeatMode() {
if (repeatSwitch == null || repeatInput == null || repeatSelectorContainer == null ||
repeatSelectedUnit == null || etRepeatValue == null) {
Log.e(TAG, "repeat mode UI components not found. Skipping setupRepeatMode.");
return;
}
repeatSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
repeatInput.setVisibility(View.VISIBLE);
repeatSelectorContainer.setVisibility(View.VISIBLE);
repeatSelectedUnit.setText(context.getString(R.string.infinitely_unit));
etRepeatValue.setText("");
etRepeatValue.setEnabled(false);
etRepeatValue.setInputType(InputType.TYPE_NULL);
} else {
repeatInput.setVisibility(View.GONE);
repeatSelectorContainer.setVisibility(View.GONE);
}
});
// 根据初始状态设置可见性
if (!repeatSwitch.isChecked()) {
repeatInput.setVisibility(View.GONE);
repeatSelectorContainer.setVisibility(View.GONE);
} else {
repeatSelectedUnit.setText(context.getString(R.string.infinitely_unit));
etRepeatValue.setText("");
etRepeatValue.setEnabled(false);
etRepeatValue.setInputType(InputType.TYPE_NULL);
}
repeatSelectorContainer.setOnClickListener(v -> showUnitSelection(v, TYPE_REPEAT));
}
private void showUnitSelection(View anchorView, int type) {
View popupView = LayoutInflater.from(context).inflate(R.layout.dialog_unit_selection, null);
PopupWindow popupWindow = new PopupWindow(
popupView,
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
true
);
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popupWindow.setOutsideTouchable(true);
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);
TextView tvInfinitely = popupView.findViewById(R.id.tv_unit_infinitely);
TextView tvDuration = popupView.findViewById(R.id.tv_unit_duration);
TextView tvCycle = popupView.findViewById(R.id.tv_unit_cycle);
switch (type) {
case TYPE_INTERVAL:
tvMs.setVisibility(View.VISIBLE);
tvSec.setVisibility(View.VISIBLE);
tvMin.setVisibility(View.VISIBLE);
tvInfinitely.setVisibility(View.GONE);
tvDuration.setVisibility(View.GONE);
tvCycle.setVisibility(View.GONE);
break;
case TYPE_SWIPE_DURATION:
tvMs.setVisibility(View.VISIBLE);
tvSec.setVisibility(View.VISIBLE);
tvMin.setVisibility(View.GONE);
tvInfinitely.setVisibility(View.GONE);
tvDuration.setVisibility(View.GONE);
tvCycle.setVisibility(View.GONE);
break;
case TYPE_REPEAT:
tvMs.setVisibility(View.GONE);
tvSec.setVisibility(View.GONE);
tvMin.setVisibility(View.GONE);
tvInfinitely.setVisibility(View.VISIBLE);
tvDuration.setVisibility(View.VISIBLE);
tvCycle.setVisibility(View.VISIBLE);
Log.d(TAG, "TYPE_REPEAT: infinitely, duration, cycle visible.");
break;
}
if (type == TYPE_INTERVAL || type == TYPE_SWIPE_DURATION) {
tvMs.setOnClickListener(v -> {
String unitText = context.getString(R.string.milliseconds_unit);
if (type == TYPE_INTERVAL) {
intervalSelectedUnit.setText(unitText);
showInputValue("Interval", etIntervalValue.getText().toString(), unitText);
} else {
tvSelectedUnit.setText(unitText);
showInputValue("Swipe Duration", etDurationValue.getText().toString(), unitText);
}
popupWindow.dismiss();
});
tvSec.setOnClickListener(v -> {
String unitText = context.getString(R.string.seconds_unit);
if (type == TYPE_INTERVAL) {
intervalSelectedUnit.setText(unitText);
showInputValue("Interval", etIntervalValue.getText().toString(), unitText);
} else {
tvSelectedUnit.setText(unitText);
showInputValue("Swipe Duration", etDurationValue.getText().toString(), unitText);
}
popupWindow.dismiss();
});
if (type == TYPE_INTERVAL) {
tvMin.setOnClickListener(v -> {
String unitText = context.getString(R.string.minutes_unit);
intervalSelectedUnit.setText(unitText);
popupWindow.dismiss();
showInputValue("Interval", etIntervalValue.getText().toString(), unitText);
});
}
}
if (type == TYPE_REPEAT) {
tvInfinitely.setOnClickListener(v -> {
repeatSelectedUnit.setText(context.getString(R.string.infinitely_unit));
etRepeatValue.setText("");
etRepeatValue.setEnabled(false);
etRepeatValue.setInputType(InputType.TYPE_NULL);
popupWindow.dismiss();
showInputValue("Repeat", etRepeatValue.getText().toString(), context.getString(R.string.infinitely_unit));
});
tvDuration.setOnClickListener(v -> {
repeatSelectedUnit.setText(context.getString(R.string.duration_unit));
etRepeatValue.setText("");
etRepeatValue.setEnabled(true);
etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER);
popupWindow.dismiss();
showInputValue("Repeat", etRepeatValue.getText().toString(), context.getString(R.string.duration_unit));
});
tvCycle.setOnClickListener(v -> {
repeatSelectedUnit.setText(context.getString(R.string.cycle_unit));
etRepeatValue.setText("");
etRepeatValue.setEnabled(true);
etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER);
popupWindow.dismiss();
showInputValue("Repeat", etRepeatValue.getText().toString(), context.getString(R.string.cycle_unit));
});
}
if (type == TYPE_REPEAT) {
popupWindow.showAsDropDown(anchorView, 0, -500);
} else {
popupWindow.showAsDropDown(anchorView);
}
}
private void showInputValue(String type, String value, String unit) {
String message = type + " 值: " + (value.isEmpty() ? "未输入" : value) + ", 单位: " + unit;
showToastOnUi(context, message);
AutoClickService service = AutoClickService.getInstance();
switch (type) {
case "Interval":
long intervalValue = 0;
if (!value.isEmpty()) {
try {
intervalValue = Long.parseLong(value);
// 根据 unit 进行单位转换
if (unit.equals(context.getString(R.string.seconds_unit))) {
intervalValue *= 1000; // 如果单位是秒转换为毫秒
}
if (service != null) {
service.setClickInterval(intervalValue);
} else {
Log.e(TAG, "AutoClickService 实例为空,无法设置点击间隔。");
}
} catch (NumberFormatException e) {
Log.e(TAG, "点击间隔值解析错误: " + value, e);
showToastOnUi(context, "点击间隔值无效,请输入有效数字。");
}
}
// 你可以在这里将 intervalValue 保存到你的数据模型或 SharedPreferences
break;
case "Swipe Duration":
int slideDurationValue = 0;
if (!value.isEmpty()) {
try {
slideDurationValue = Integer.parseInt(value);
if (unit.equals(context.getString(R.string.seconds_unit))) {
slideDurationValue *= 1000; // 如果单位是秒转换为毫秒
}
if (service != null) {
service.setSlideDuration(slideDurationValue);
} else {
Log.e(TAG, "AutoClickService 实例为空,无法设置滑动时长。");
}
} catch (NumberFormatException e) {
Log.e(TAG, "滑动时长值解析错误: " + value, e);
showToastOnUi(context, "滑动时长值无效,请输入有效数字。");
}
}
// 你可以在这里将 slideDurationValue 保存到你的数据模型或 SharedPreferences
break;
case "Repeat":
if (unit.equals(context.getString(R.string.infinitely_unit))) {
// Repeat 为无限次不需要处理输入值
// 确保 etRepeatValue 是禁用的
etRepeatValue.setText("");
etRepeatValue.setEnabled(false);
etRepeatValue.setInputType(InputType.TYPE_NULL);
showToastOnUi(context, "重复模式: 无限次");
// AutoClickService 内部已是循环执行无限次意味着一直运行直到用户停止
// 如果需要更明确的无限次模式可以在 AutoClickService 中设置一个标志位
} else if (unit.equals(context.getString(R.string.duration_unit))) {
// Repeat 为时长处理时间格式的输入 (例如 "HH:mm:ss" -> 毫秒)
String durationValueStr = value.isEmpty() ? "0" : value;
// TODO: 你需要在这里添加解析时间格式的逻辑例如
// long parsedDuration = parseDurationString(durationValueStr); // 自定义方法解析时间
// 如果 AutoClickService 需要总运行时间限制你需要修改 AutoClickService 来支持
// 否则你可能需要在悬浮窗管理类中实现一个计时器当达到设定时长时调用 service.stopClicking()
etRepeatValue.setEnabled(true);
etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER); // 这里暂时设置为数字如果需要特定时间输入需要更复杂的实现
showToastOnUi(context, "重复时长: " + durationValueStr);
} else if (unit.equals(context.getString(R.string.cycle_unit))) {
// Repeat 为次数处理整数输入
int repeatCount = 0;
if (!value.isEmpty()) {
try {
repeatCount = Integer.parseInt(value);
// TODO: 如果 AutoClickService 需要总循环次数限制你需要修改 AutoClickService 来支持
// 可以在 AutoClickService 中添加一个变量来跟踪剩余循环次数并在每次事件队列执行完毕后递减
// 当次数为 0 调用 stopClicking()
} catch (NumberFormatException e) {
Log.e(TAG, "重复次数值解析错误: " + value, e);
showToastOnUi(context, "重复次数值无效,请输入有效数字。");
}
}
etRepeatValue.setEnabled(true);
etRepeatValue.setInputType(InputType.TYPE_CLASS_NUMBER);
showToastOnUi(context, "重复次数: " + repeatCount);
}
break;
}
}
public static void showToastOnUi(Context context, String msg) {
new Handler(Looper.getMainLooper()).post(() ->
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
);
}
}

View File

@ -1,6 +1,5 @@
package com.auto.clicker.autoclicker.view;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -12,7 +11,6 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
@ -21,15 +19,12 @@ 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;
import androidx.appcompat.app.AlertDialog;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.auto.clicker.autoclicker.R;
@ -80,6 +75,7 @@ public class FloatingViewManager {
private boolean areEventsVisible = true;
private final FloatingTabDialogManager floatingTabDialogManager;
private final FloatingSettingDialogManager floatingSettingDialogManager;
private final EventRepository eventRepository;
@ -97,7 +93,9 @@ public class FloatingViewManager {
this.screenWidth = screenSize.x;
this.screenHeight = screenSize.y;
this.floatingTabDialogManager = new FloatingTabDialogManager(context);
this.floatingSettingDialogManager = new FloatingSettingDialogManager(context);
this.floatingTabDialogManager.setFloatingViewManager(this);
this.floatingSettingDialogManager.setFloatingViewManager(this);
this.eventRepository = new EventRepository(context.getApplicationContext());
this.touchPointSize = 100;
@ -238,6 +236,7 @@ public class FloatingViewManager {
addButton.setVisibility(View.GONE);
removeButton.setVisibility(View.GONE);
slideButton.setVisibility(View.GONE);
addPointEvent();
}
playButton.setOnClickListener(v -> toggleMultipleClicking());
@ -259,7 +258,9 @@ public class FloatingViewManager {
}
});
settingButton.setOnClickListener(v -> showInputDialog());
settingButton.setOnClickListener(v -> {
floatingSettingDialogManager.showFloatingTabDialog();
});
closeButton.setOnClickListener(v -> closeFloatingViews());
}
@ -413,7 +414,7 @@ public class FloatingViewManager {
PrefUtils.setFloatingShown(context, 0);
Intent intent = new Intent("com.auto.clicker.autoclicker.FLOATING_WINDOW_STATE_CHANGED");
intent.putExtra("isShown", false);
intent.putExtra("isShown", 0);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
@ -459,6 +460,10 @@ public class FloatingViewManager {
floatingTabDialogManager.removeFloatingTabDialog();
}
if (floatingSettingDialogManager != null) {
floatingSettingDialogManager.removeFloatingTabDialog();
}
Log.d(TAG, "所有浮动视图(包括控制栏和事件)已移除");
}
@ -535,55 +540,6 @@ public class FloatingViewManager {
}
}
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(int index) {
if (index >= 0 && index < runtimeEvents.size()) {
Event event = runtimeEvents.get(index).getEvent();

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="47dp"
android:height="47dp"
android:viewportWidth="47"
android:viewportHeight="47">
<path
android:pathData="M23.5,0C10.522,0 0,10.522 0,23.5C0,36.478 10.522,47 23.5,47C36.478,47 47,36.478 47,23.5C47,10.522 36.478,0 23.5,0ZM23.743,44.908C23.743,44.908 23.788,44.786 23.788,44.726V40.177C23.788,39.601 23.318,39.146 22.757,39.146C22.196,39.146 21.726,39.617 21.726,40.177V44.726C21.726,44.726 21.741,44.802 21.741,44.832C11.098,43.953 2.653,35.265 2.138,24.531H6.08C6.656,24.531 7.111,24.061 7.111,23.5C7.111,22.939 6.641,22.469 6.08,22.469H2.123C2.638,11.72 11.083,3.047 21.726,2.168C21.726,2.214 21.711,2.244 21.711,2.274V6.823C21.711,7.399 22.181,7.854 22.742,7.854C23.303,7.854 23.773,7.384 23.773,6.823V2.274C23.773,2.274 23.743,2.153 23.727,2.092C35.083,2.214 44.317,11.219 44.862,22.469H40.92C40.344,22.469 39.889,22.939 39.889,23.5C39.889,24.061 40.359,24.531 40.92,24.531H44.862C44.317,35.781 35.083,44.786 23.727,44.908H23.743Z"
android:fillColor="#57FC0B"/>
</vector>

View File

@ -1,9 +1,6 @@
<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="M502.7,448a56,56 0,1 0,0 112,56 56,0 0,0 0,-112zM502.7,96C277.3,96 94.6,278.7 94.6,504S277.3,912 502.6,912C728,912 910.7,729.3 910.7,504S728,96 502.7,96zM544,829.3L544,688h-80v141.3C320,811.1 195.5,688 177.3,544L320,544v-80h-142.7C195.5,320 320,196.8 464,178.7L464,320h80v-141.3C688,196.8 809.8,320 828,464L688,464v80h140C809.8,688 688,811.2 544,829.3z"
android:fillColor="#FF0057"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/blue_ring_bg" />
<item android:drawable="@drawable/green_ring" />
</layer-list>

View File

@ -0,0 +1,288 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="321dp"
android:layout_height="386dp"
android:background="@drawable/bg_rounded_rect"
android:paddingBottom="25dp">
<TextView
android:id="@+id/tv_default_actions_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="35dp"
android:layout_marginTop="23dp"
android:text="Default Actions"
android:textColor="@color/text_gray"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_interval_icon"
android:layout_width="11dp"
android:layout_height="12dp"
android:layout_marginEnd="8dp"
android:src="@drawable/hourglass"
app:layout_constraintBottom_toBottomOf="@+id/tv_interval_label"
app:layout_constraintEnd_toStartOf="@+id/tv_interval_label"
app:layout_constraintTop_toTopOf="@+id/tv_interval_label" />
<TextView
android:id="@+id/tv_interval_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="56dp"
android:layout_marginTop="9dp"
android:text="Interval between actions"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_default_actions_title" />
<LinearLayout
android:id="@+id/input_interval"
android:layout_width="287dp"
android:layout_height="42dp"
android:layout_marginStart="20dp"
android:layout_marginTop="9dp"
android:layout_marginEnd="20dp"
android:background="@drawable/rounded_edittext_background"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_interval_label">
<EditText
android:id="@+id/dialog_et_interval_value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:inputType="number"
android:padding="8dp"
android:textColor="@color/white"
android:textColorHint="@color/gray" />
<LinearLayout
android:id="@+id/dialog_interval_selector_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="4dp">
<TextView
android:id="@+id/dialog_interval_selected_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="4dp"
android:text="milliseconds"
android:textColor="@color/white"
android:textSize="14sp" />
<ImageView
android:id="@+id/interval_unit_dropdown"
android:layout_width="15dp"
android:layout_height="8dp"
android:src="@drawable/blue_arrow_down" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/duration_icon"
android:layout_width="20dp"
android:layout_height="11dp"
android:src="@drawable/left_swipe"
app:layout_constraintBottom_toBottomOf="@+id/tv_swipe_duration_label"
app:layout_constraintEnd_toEndOf="@id/iv_interval_icon"
app:layout_constraintTop_toTopOf="@id/tv_swipe_duration_label" />
<TextView
android:id="@+id/tv_swipe_duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Swipe duration"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/tv_interval_label"
app:layout_constraintTop_toBottomOf="@id/input_interval" />
<TextView
android:id="@+id/tv_preview_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="41dp"
android:text="@string/preview"
android:textColor="@color/blue"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/tv_swipe_duration_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_swipe_duration_label" />
<LinearLayout
android:id="@+id/input_with_unit_container"
android:layout_width="287dp"
android:layout_height="42dp"
android:layout_marginStart="20dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="8dp"
android:background="@drawable/rounded_edittext_background"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_swipe_duration_label">
<EditText
android:id="@+id/dialog_et_duration_value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:inputType="number"
android:padding="8dp"
android:textColor="@color/white"
android:textColorHint="@color/gray" />
<LinearLayout
android:id="@+id/dialog_unit_selector_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="4dp">
<TextView
android:id="@+id/dialog_tv_selected_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="4dp"
android:text="milliseconds"
android:textColor="@color/white"
android:textSize="14sp" />
<ImageView
android:id="@+id/iv_unit_dropdown"
android:layout_width="15dp"
android:layout_height="8dp"
android:src="@drawable/blue_arrow_down" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/default_cycle_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="35dp"
android:layout_marginTop="23dp"
android:text="Default cycle"
android:textColor="@color/text_gray"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/input_with_unit_container" />
<ImageView
android:id="@+id/repeat_icon"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_marginEnd="9dp"
android:src="@drawable/cycle"
app:layout_constraintBottom_toBottomOf="@+id/repeat_text"
app:layout_constraintEnd_toStartOf="@+id/repeat_text"
app:layout_constraintTop_toTopOf="@+id/repeat_text" />
<TextView
android:id="@+id/repeat_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="56dp"
android:layout_marginTop="9dp"
android:text="Repeat mode"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/default_cycle_title" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/dialog_repeat_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
app:layout_constraintBottom_toBottomOf="@+id/repeat_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/repeat_text"
app:layout_constraintVertical_bias="0.31"
app:thumbTint="@color/switch_thumb_selector"
app:trackTint="@color/switch_track_selector" />
<LinearLayout
android:id="@+id/dialog_repeat_input"
android:layout_width="287dp"
android:layout_height="48dp"
android:layout_marginStart="20dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingEnd="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/repeat_text">
<EditText
android:id="@+id/dialog_et_repeat_value"
android:layout_width="123dp"
android:layout_height="42dp"
android:background="@drawable/rounded_edittext_background"
android:inputType="number"
android:padding="8dp"
android:textColor="@color/white"
android:textColorHint="@color/gray" />
<LinearLayout
android:id="@+id/dialog_repeat_selector_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="62dp"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="4dp">
<TextView
android:id="@+id/dialog_repeat_selected_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="4dp"
android:text="infinitely"
android:textColor="@color/white"
android:textSize="14sp" />
<ImageView
android:id="@+id/repeat_unit_dropdown"
android:layout_width="15dp"
android:layout_height="8dp"
android:src="@drawable/blue_arrow_down" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>