fixed spinner infinite loop in appointments
This commit is contained in:
@@ -10,6 +10,7 @@ import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
|||||||
import com.example.petstoremobile.adapters.WhiteTextArrayAdapter;
|
import com.example.petstoremobile.adapters.WhiteTextArrayAdapter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -51,6 +52,12 @@ public class SpinnerUtils {
|
|||||||
names.add(nameExtractor.apply(item));
|
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;
|
ArrayAdapter<String> adapter;
|
||||||
if (useWhiteText) {
|
if (useWhiteText) {
|
||||||
adapter = new WhiteTextArrayAdapter<>(context, android.R.layout.simple_spinner_item, names);
|
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);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinner.setAdapter(adapter);
|
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) {
|
if (preselectedId != null && preselectedId != -1) {
|
||||||
int offset = (defaultText != null) ? 1 : 0;
|
int offset = (defaultText != null) ? 1 : 0;
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (int i = 0; i < data.size(); i++) {
|
||||||
Long currentId = idExtractor.apply(data.get(i));
|
Long currentId = idExtractor.apply(data.get(i));
|
||||||
if (Objects.equals(currentId, preselectedId)) {
|
if (Objects.equals(currentId, preselectedId)) {
|
||||||
spinner.setSelection(i + offset);
|
if (spinner.getSelectedItemPosition() != i + offset) {
|
||||||
|
spinner.setSelection(i + offset);
|
||||||
|
}
|
||||||
break;
|
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.
|
* Sets up a simple string spinner for filtering with a callback.
|
||||||
*/
|
*/
|
||||||
public static void setupStringFilterSpinner(Context context, Spinner spinner, String[] items, Runnable onSelectionChanged) {
|
public static void setupStringFilterSpinner(Context context, Spinner spinner, String[] items, Runnable onSelectionChanged) {
|
||||||
WhiteTextArrayAdapter<String> adapter = new WhiteTextArrayAdapter<>(context,
|
updateStringSpinnerIfChanged(context, spinner, items, true);
|
||||||
android.R.layout.simple_spinner_item, items);
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
spinner.setAdapter(adapter);
|
|
||||||
setupFilterSpinner(spinner, onSelectionChanged);
|
setupFilterSpinner(spinner, onSelectionChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +133,7 @@ public class SpinnerUtils {
|
|||||||
if (value == null || spinner.getAdapter() == null) return;
|
if (value == null || spinner.getAdapter() == null) return;
|
||||||
ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
|
ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
|
||||||
int pos = adapter.getPosition(value);
|
int pos = adapter.getPosition(value);
|
||||||
if (pos >= 0) {
|
if (pos >= 0 && spinner.getSelectedItemPosition() != pos) {
|
||||||
spinner.setSelection(pos);
|
spinner.setSelection(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +145,9 @@ public class SpinnerUtils {
|
|||||||
if (spinner == null || array == null || value == null) return;
|
if (spinner == null || array == null || value == null) return;
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
if (Objects.equals(array[i], value)) {
|
if (Objects.equals(array[i], value)) {
|
||||||
spinner.setSelection(i);
|
if (spinner.getSelectedItemPosition() != i) {
|
||||||
|
spinner.setSelection(i);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,8 +157,21 @@ public class SpinnerUtils {
|
|||||||
* Configures a simple string array spinner.
|
* Configures a simple string array spinner.
|
||||||
*/
|
*/
|
||||||
public static void setupStringSpinner(Context context, Spinner spinner, String[] items) {
|
public static void setupStringSpinner(Context context, Spinner spinner, String[] items) {
|
||||||
BlackTextArrayAdapter<String> adapter = new BlackTextArrayAdapter<>(context,
|
updateStringSpinnerIfChanged(context, spinner, items, false);
|
||||||
android.R.layout.simple_spinner_item, items);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinner.setAdapter(adapter);
|
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) {
|
public static void setViewsEnabled(boolean enabled, View... views) {
|
||||||
for (View v : views) {
|
for (View v : views) {
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
v.setEnabled(enabled);
|
if (v.isEnabled() != enabled) {
|
||||||
v.setAlpha(enabled ? 1.0f : 0.5f);
|
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) {
|
public static void setFieldEnabled(boolean enabled, View field, View label) {
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
field.setEnabled(enabled);
|
if (field.isEnabled() != enabled) {
|
||||||
field.setAlpha(enabled ? 1.0f : 0.5f);
|
field.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
float targetAlpha = enabled ? 1.0f : 0.5f;
|
||||||
|
if (Math.abs(field.getAlpha() - targetAlpha) > 0.01f) {
|
||||||
|
field.setAlpha(targetAlpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (label != null) {
|
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) {
|
public static void setViewsAlpha(float alpha, View... views) {
|
||||||
for (View v : views) {
|
for (View v : views) {
|
||||||
if (v != null) {
|
if (v != null && Math.abs(v.getAlpha() - alpha) > 0.01f) {
|
||||||
v.setAlpha(alpha);
|
v.setAlpha(alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user