blob: 4c4b11489ddacc2f81214cf3341a52dab7ab3782 [file]
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT;
import static com.android.settings.accessibility.AutoclickUtils.AUTOCLICK_DELAY_STEP;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.google.common.collect.ImmutableBiMap;
/**
* Fragment for creating a dialog in autoclick settings.
*/
public class AutoclickDelayDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = AutoclickDelayDialogFragment.class.getSimpleName();
public final ImmutableBiMap<Integer, Integer> RADIO_BUTTON_ID_TO_DELAY_TIME =
new ImmutableBiMap.Builder<Integer, Integer>()
.put(R.id.accessibility_autoclick_dialog_600ms, 600)
.put(R.id.accessibility_autoclick_dialog_800ms, 800)
.put(R.id.accessibility_autoclick_dialog_1sec, 1000)
.put(R.id.accessibility_autoclick_dialog_2sec, 2000)
.put(R.id.accessibility_autoclick_dialog_4sec, 4000)
.buildOrThrow();
/** Create an AutoclickDelayDialogFragment instance. */
public static @NonNull AutoclickDelayDialogFragment newInstance() {
return new AutoclickDelayDialogFragment();
}
public int getMetricsCategory() {
return SettingsEnums.ACCESSIBILITY_TOGGLE_AUTOCLICK;
}
@Override
public @NonNull Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
View dialogView = LayoutInflater.from(getContext())
.inflate(R.layout.dialog_autoclick_delay_before_click, /* root= */ null);
getRadioButtonLabels(dialogView);
RadioGroup radioGroup = dialogView.findViewById(
R.id.autoclick_delay_before_click_value_group);
SeekBar customProgressBar = dialogView.findViewById(
R.id.accessibility_autoclick_custom_slider);
TextView customValueTextView = dialogView.findViewById(
R.id.accessibility_autoclick_custom_value);
Group sliderContainer = dialogView.findViewById(R.id.sliderContainer);
ImageView decreaseButton = dialogView.findViewById(
R.id.accessibility_autoclick_custom_value_decrease);
ImageView increaseButton = dialogView.findViewById(
R.id.accessibility_autoclick_custom_value_increase);
AlertDialog alertDialog = new AlertDialog.Builder(getContext())
.setView(dialogView)
.setPositiveButton(android.R.string.ok,
(dialog, which) -> {
int checkedRadioButtonId =
radioGroup.getCheckedRadioButtonId();
int delay = AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT;
if (RADIO_BUTTON_ID_TO_DELAY_TIME
.containsKey(checkedRadioButtonId)) {
delay = RADIO_BUTTON_ID_TO_DELAY_TIME.get(checkedRadioButtonId);
} else {
delay = seekBarProgressToDelay(customProgressBar.getProgress());
}
updateAutoclickDelay(delay);
})
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss())
.create();
radioGroup.setOnCheckedChangeListener((buttonView, checkedId) -> {
customValueTextView.setText(delayTimeToString(
seekBarProgressToDelay(customProgressBar.getProgress())));
sliderContainer.setVisibility(
isCustomButtonChecked(checkedId) ? View.VISIBLE : View.GONE);
});
customProgressBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(
@NonNull SeekBar seekBar, int progress, boolean fromUser) {
CharSequence threshold = delayTimeToString(seekBarProgressToDelay(progress));
customValueTextView.setText(threshold);
}
@Override
public void onStartTrackingTouch(@NonNull SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(@NonNull SeekBar seekBar) {
}
});
decreaseButton.setOnClickListener(v -> decreaseDelayByImageView(customProgressBar));
increaseButton.setOnClickListener(v -> increaseDelayByImageView(customProgressBar));
if (savedInstanceState == null) {
initStateBasedOnDelay(radioGroup, customValueTextView, customProgressBar);
}
return alertDialog;
}
private void initStateBasedOnDelay(@NonNull RadioGroup radioGroup,
@NonNull TextView customValueTextView, @NonNull SeekBar customProgressBar) {
final int autoclickDelay = Settings.Secure.getInt(getContext().getContentResolver(),
Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
AccessibilityManager.AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT);
customValueTextView.setText(delayTimeToString(autoclickDelay));
customProgressBar.setProgress(autoclickDelay / AUTOCLICK_DELAY_STEP);
Integer radioButtonId = RADIO_BUTTON_ID_TO_DELAY_TIME.inverse().get(autoclickDelay);
if (radioButtonId != null) {
radioGroup.check(radioButtonId);
} else {
radioGroup.check(R.id.accessibility_autoclick_dialog_custom);
}
}
private void decreaseDelayByImageView(@NonNull SeekBar customProgressBar) {
int delay = customProgressBar.getProgress();
if (delay > customProgressBar.getMin()) {
delay--;
}
customProgressBar.setProgress(delay);
}
private void increaseDelayByImageView(@NonNull SeekBar customProgressBar) {
int delay = customProgressBar.getProgress();
if (delay < customProgressBar.getMax()) {
delay++;
}
customProgressBar.setProgress(delay);
}
private boolean isCustomButtonChecked(int checkedId) {
return checkedId == R.id.accessibility_autoclick_dialog_custom;
}
private void getRadioButtonLabels(@NonNull View dialogView) {
for (Integer radioButtonId : RADIO_BUTTON_ID_TO_DELAY_TIME.keySet()) {
RadioButton radioButton = dialogView.findViewById(radioButtonId);
if (radioButton != null) {
radioButton.setText(delayTimeToString(
RADIO_BUTTON_ID_TO_DELAY_TIME.get(radioButtonId)));
}
}
}
// LINT.IfChange
/** Converts seek bar preference progress value to autoclick delay associated with it. */
private int seekBarProgressToDelay(int progress) {
return progress * AUTOCLICK_DELAY_STEP;
}
// LINT.ThenChange(autoclick/ui/AutoclickDelayPreference.kt)
private CharSequence delayTimeToString(int delayMillis) {
return AutoclickUtils.getAutoclickDelaySummary(getContext(),
R.string.accessibility_autoclick_delay_unit_second, delayMillis);
}
/** Updates autoclick delay time. */
private void updateAutoclickDelay(int delay) {
Settings.Secure.putInt(
getContext().getContentResolver(),
Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
delay);
}
}