Ich versuche, ein „Mehr“ -Taste für einen Spinner zu implementieren. Grundsätzlich möchte ich zunächst nur ein paar Elemente anzeigen und wenn der Benutzer auf den letzten Eintrag ("Mehr ...") klickt, ändert sich der Spinner und zeigt alle Einträge an.Android: Ändern Spinner Artikel ohne Schließen der Spinner
Also die Funktion, die ich hier brauche, ist eine Möglichkeit, Spinner Artikel ohne zu ändern, den Spinner zu schließen. Ich habe alles bis auf den letzten Teil geschafft. Jedes Mal, wenn ich die Gegenstände ändere, wird der Spinner automatisch geschlossen (ohne den Fokus zu verlieren).
Die einzige Abhilfe, die ich dachte, war mSpinner.performClick()
zu verwenden, sofort den Spinner zu öffnen, nachdem es geschlossen wird. Natürlich ist das nicht gut genug, weil ich diesen schnellen Close-Reopen-Effekt bekomme. Nicht cool.
ich eine benutzerdefinierte Spinner-Klasse erstellt, die die Logik verwaltet:
public class ReservationStatusSpinner extends Spinner {
// --------------------------------------------------
// State
// --------------------------------------------------
private final String mMoreStatus;
private OnItemSelectedListener mUserListener;
private ArrayAdapter<String> mAdapter;
private boolean mOpenInitiated = false;
// --------------------------------------------------
// Interfaces
// --------------------------------------------------
private interface OnSpinnerEventsListener {
// Not needed, but may be needed in the future -> void onSpinnerOpened();
void onSpinnerClosed();
}
private OnSpinnerEventsListener mOnSpinnerEventsListener;
public interface OnStatusSelectedListener {
void onStatusSelected(String status);
}
private OnStatusSelectedListener mOnStatusSelectedListener;
// --------------------------------------------------
// Construction/Initialization
// --------------------------------------------------
public ReservationStatusSpinner(Context context) {
super(context);
mMoreStatus = getContext().getResources().getString(R.string.status_more);
init();
}
public ReservationStatusSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
mMoreStatus = getContext().getResources().getString(R.string.status_more);
init();
}
private void init() {
// Add listener
super.setOnItemSelectedListener(new OnItemSelected());
mOnSpinnerEventsListener = new OnSpinnerEventsListener() {
@Override
public void onSpinnerClosed() {
filterAndSelect();
}
};
}
// --------------------------------------------------
// Overridden methods
// --------------------------------------------------
@Override
public boolean performClick() {
// register that the Spinner was opened so we have a status
// indicator for the activity(which may lose focus for some other
// reasons)
mOpenInitiated = true;
return super.performClick();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
// mSpin is our custom Spinner
if (mOpenInitiated && hasFocus) {
performClosedEvent();
}
}
@Override
public void setOnItemSelectedListener(OnItemSelectedListener l) {
mUserListener = l;
}
// --------------------------------------------------
// Private methods
// --------------------------------------------------
private static ArrayList<String> getAllStatuses(Context context) {
ArrayList<String> items = new ArrayList<>();
CharSequence[] statusesCSArray = context.getResources().getTextArray(R.array.reservation_status);
for (CharSequence cs : statusesCSArray)
items.add(cs.toString());
return items;
}
private void performClosedEvent() {
mOpenInitiated = false;
if (mOnSpinnerEventsListener != null) {
mOnSpinnerEventsListener.onSpinnerClosed();
}
}
private void filterAndSelect() {
List<String> items = filterStatuses((String)getSelectedItem(), mMoreStatus);
setItems(items);
setSelection(0);
}
// --------------------------------------------------
// Public methods
// --------------------------------------------------
public void setStatus(String status) {
// Find status in adapter
int pos = -1;
for (int i = 0; i < mAdapter.getCount(); ++i) {
if (mAdapter.getItem(i).equals(status)) {
pos = i;
break;
}
}
if (pos != -1)
setSelection(pos);
}
public void setAdapter(ArrayAdapter<String> adapter) {
super.setAdapter(adapter);
mAdapter = adapter;
}
public void setOnStatusSelectedListener(OnStatusSelectedListener l) {
mOnStatusSelectedListener = l;
}
public void setItems(List<String> items) {
mAdapter.clear();
mAdapter.addAll(items);
mAdapter.notifyDataSetChanged();
}
// --------------------------------------------------
// Utilities
// --------------------------------------------------
public static ArrayList<String> filterStatuses(String selectedStatus, String moreStatus) {
ArrayList<String> list = new ArrayList<>(DataUtilities.filterStatuses(selectedStatus));
// Add selected status at start
list.add(0, selectedStatus);
// Append "More"
list.add(moreStatus);
return list;
}
// --------------------------------------------------
// Custom ItemSelectedListener for ReservationStatusSpinner
// --------------------------------------------------
private class OnItemSelected implements OnItemSelectedListener {
private String mPreviousStatus;
private boolean mMoreClicked = false;
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String more = getContext().getResources().getString(R.string.status_more);
String status = getSelectedItem().toString();
ArrayList<String> items = new ArrayList<>();
if (status.equals(more)) {
items.addAll(getAllStatuses(getContext()));
items.remove(mMoreStatus);
setItems(items);
//setStatus(mPreviousStatus);
mMoreClicked = true;
// Reopen spinner (it closes after changing data) (TODO: Fix this)
ReservationStatusSpinner.this.performClick();
} else if (!mMoreClicked) {
filterAndSelect();
}
if (!status.equals(more)) {
if (mUserListener != null)
mUserListener.onItemSelected(parent, view, position, id);
if (mOnStatusSelectedListener != null)
mOnStatusSelectedListener.onStatusSelected(status);
}
mPreviousStatus = status;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
if (mUserListener != null)
mUserListener.onNothingSelected(parent);
}
}
}
und einen benutzerdefinierten Adapter:
public class ImageSpinnerAdapter extends ArrayAdapter<String> {
private LayoutInflater mInflater;
public ImageSpinnerAdapter(Context context, int textViewResourceId, List<String> titles) {
super(context, textViewResourceId, titles);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
View view;
if (convertView == null) {
view = mInflater.inflate(R.layout.row_image_spinner_dropdown, parent, false);
} else {
view = convertView;
}
ImageView icon = (ImageView)view.findViewById(R.id.spinner_icon);
setIcon(icon, getItem(position));
TextView text = (TextView)view.findViewById(R.id.spinner_status_text);
text.setText(DataUtilities.addWhitespacesToStatus(getItem(position)));
view.setPadding(0, 0, 0, 0);
return view;
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
View view;
if (convertView == null) {
view = mInflater.inflate(R.layout.row_image_spinner_view, parent, false);
} else {
view = convertView;
}
// Set icon
ImageView icon = (ImageView)view.findViewById(R.id.spinner_icon);
setIcon(icon, getItem(position));
view.setPadding(0, 0, 0, 0);
return view;
}
private void setIcon(ImageView icon, String status) {
// Make sure there are no whitespaces in status
status = DataUtilities.removeWhitespaceFromStatus(status);
// Get the correct image for each status
icon.setImageResource(DataUtilities.statusToIconResource(status));
}
}
In meinem Spinner, die meiste Arbeit in den private class OnItemSelected
am Ende getan des Schnipsel.
Zuerst dachte ich, das Problem der Konvertit Blick auf meinem Adapter (ich war nicht das convert Ansicht Muster zunächst mit), aber wie man sehen kann ich es jetzt bin mit.
Das Problem tritt auf 2 verschiedenen Geräten und mein Emulator so, es ist sicher anzunehmen, dass es kein Gerät spezifisches Problem ist.
Wer irgendwelche Ideen oder irgendwelche Hinweise?
So gibt es keine Möglichkeit zum Hinzufügen/Löschen von Elementen aus einem dynamisch Spinnern? – TheCrafter
@TheCrafter - Zum Hinzufügen/Löschen müssen Sie hinzufügen/entfernen von Arraylist und NotifyDataSetChanged() auf ItemSelected() -Methode aufrufen. – Ragini
Das mache ich schon. Es aktualisiert zwar das Adapter-Dataset, schließt das Spinner jedoch automatisch. Ich suche nach einer Möglichkeit, dies zu tun, ohne den Spinner zu schließen. – TheCrafter