fixed spinner infinite loop in appointments
This commit is contained in:
@@ -176,7 +176,7 @@ public class AppointmentDetailFragment extends Fragment {
|
||||
*/
|
||||
private void applyViewState(AppointmentDetailViewModel.ViewState state) {
|
||||
isUpdatingUI = true;
|
||||
|
||||
|
||||
// Mode specific UI
|
||||
binding.tvApptMode.setText(state.isEditing ? "Edit Appointment" : "Add Appointment");
|
||||
binding.tvAppointmentId.setText(DateTimeUtils.formatId(appointmentViewModel.getAppointmentId()));
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
||||
import com.example.petstoremobile.adapters.WhiteTextArrayAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
@@ -51,6 +52,12 @@ public class SpinnerUtils {
|
||||
names.add(nameExtractor.apply(item));
|
||||
}
|
||||
|
||||
// Only update adapter if contents changed to remove infinite loop when spinner is opened
|
||||
if (isAdapterDataSame(spinner, names)) {
|
||||
setSelectedId(spinner, data, defaultText, preselectedId, idExtractor);
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayAdapter<String> adapter;
|
||||
if (useWhiteText) {
|
||||
adapter = new WhiteTextArrayAdapter<>(context, android.R.layout.simple_spinner_item, names);
|
||||
@@ -61,26 +68,41 @@ public class SpinnerUtils {
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
|
||||
setSelectedId(spinner, data, defaultText, preselectedId, idExtractor);
|
||||
}
|
||||
|
||||
private static <T> void setSelectedId(Spinner spinner, List<T> data, String defaultText, Long preselectedId, Function<T, Long> idExtractor) {
|
||||
if (preselectedId != null && preselectedId != -1) {
|
||||
int offset = (defaultText != null) ? 1 : 0;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
Long currentId = idExtractor.apply(data.get(i));
|
||||
if (Objects.equals(currentId, preselectedId)) {
|
||||
spinner.setSelection(i + offset);
|
||||
if (spinner.getSelectedItemPosition() != i + offset) {
|
||||
spinner.setSelection(i + offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the adapter data is the same as the new data.
|
||||
*/
|
||||
private static boolean isAdapterDataSame(Spinner spinner, List<String> newNames) {
|
||||
if (spinner.getAdapter() == null) return false;
|
||||
if (spinner.getAdapter().getCount() != newNames.size()) return false;
|
||||
for (int i = 0; i < newNames.size(); i++) {
|
||||
if (!Objects.equals(spinner.getAdapter().getItem(i), newNames.get(i))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a simple string spinner for filtering with a callback.
|
||||
*/
|
||||
public static void setupStringFilterSpinner(Context context, Spinner spinner, String[] items, Runnable onSelectionChanged) {
|
||||
WhiteTextArrayAdapter<String> adapter = new WhiteTextArrayAdapter<>(context,
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
updateStringSpinnerIfChanged(context, spinner, items, true);
|
||||
setupFilterSpinner(spinner, onSelectionChanged);
|
||||
}
|
||||
|
||||
@@ -111,7 +133,7 @@ public class SpinnerUtils {
|
||||
if (value == null || spinner.getAdapter() == null) return;
|
||||
ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
|
||||
int pos = adapter.getPosition(value);
|
||||
if (pos >= 0) {
|
||||
if (pos >= 0 && spinner.getSelectedItemPosition() != pos) {
|
||||
spinner.setSelection(pos);
|
||||
}
|
||||
}
|
||||
@@ -123,7 +145,9 @@ public class SpinnerUtils {
|
||||
if (spinner == null || array == null || value == null) return;
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (Objects.equals(array[i], value)) {
|
||||
spinner.setSelection(i);
|
||||
if (spinner.getSelectedItemPosition() != i) {
|
||||
spinner.setSelection(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -133,8 +157,21 @@ public class SpinnerUtils {
|
||||
* Configures a simple string array spinner.
|
||||
*/
|
||||
public static void setupStringSpinner(Context context, Spinner spinner, String[] items) {
|
||||
BlackTextArrayAdapter<String> adapter = new BlackTextArrayAdapter<>(context,
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
updateStringSpinnerIfChanged(context, spinner, items, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a string spinner only if the items have changed.
|
||||
*/
|
||||
public static void updateStringSpinnerIfChanged(Context context, Spinner spinner, String[] items, boolean useWhiteText) {
|
||||
if (isAdapterDataSame(spinner, Arrays.asList(items))) return;
|
||||
|
||||
ArrayAdapter<String> adapter;
|
||||
if (useWhiteText) {
|
||||
adapter = new WhiteTextArrayAdapter<>(context, android.R.layout.simple_spinner_item, items);
|
||||
} else {
|
||||
adapter = new BlackTextArrayAdapter<>(context, android.R.layout.simple_spinner_item, items);
|
||||
}
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
}
|
||||
|
||||
@@ -73,36 +73,49 @@ public class UIUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the enabled state and alpha for multiple views.
|
||||
* Sets the enabled state and alpha for multiple views, only if changed.
|
||||
*/
|
||||
public static void setViewsEnabled(boolean enabled, View... views) {
|
||||
for (View v : views) {
|
||||
if (v != null) {
|
||||
v.setEnabled(enabled);
|
||||
v.setAlpha(enabled ? 1.0f : 0.5f);
|
||||
if (v.isEnabled() != enabled) {
|
||||
v.setEnabled(enabled);
|
||||
}
|
||||
float targetAlpha = enabled ? 1.0f : 0.5f;
|
||||
if (Math.abs(v.getAlpha() - targetAlpha) > 0.01f) {
|
||||
v.setAlpha(targetAlpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets enabled state for a field and updates alpha for both the field and its label.
|
||||
* Sets enabled state for a field and updates alpha for both the field and its label, only if changed.
|
||||
*/
|
||||
public static void setFieldEnabled(boolean enabled, View field, View label) {
|
||||
if (field != null) {
|
||||
field.setEnabled(enabled);
|
||||
field.setAlpha(enabled ? 1.0f : 0.5f);
|
||||
if (field.isEnabled() != enabled) {
|
||||
field.setEnabled(enabled);
|
||||
}
|
||||
float targetAlpha = enabled ? 1.0f : 0.5f;
|
||||
if (Math.abs(field.getAlpha() - targetAlpha) > 0.01f) {
|
||||
field.setAlpha(targetAlpha);
|
||||
}
|
||||
}
|
||||
if (label != null) {
|
||||
label.setAlpha(enabled ? 1.0f : 0.5f);
|
||||
float targetAlpha = enabled ? 1.0f : 0.5f;
|
||||
if (Math.abs(label.getAlpha() - targetAlpha) > 0.01f) {
|
||||
label.setAlpha(targetAlpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the alpha for multiple views.
|
||||
* Sets the alpha for multiple views, only if changed.
|
||||
*/
|
||||
public static void setViewsAlpha(float alpha, View... views) {
|
||||
for (View v : views) {
|
||||
if (v != null) {
|
||||
if (v != null && Math.abs(v.getAlpha() - alpha) > 0.01f) {
|
||||
v.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user