회 전자에 "추가"버튼을 구현하려고합니다. 기본적으로 몇 가지 항목 만 표시하고 마지막 항목 ("자세히 ...")을 클릭하면 회 전자가 변경되어 모든 항목을 표시합니다.Android : 회 전자를 닫지 않고 회 전자 항목 바꾸기
여기서 필자가 필요로하는 기능은 스피너 항목을 동적으로 변경하는 방법입니다. 회 전자를 닫지 않아도됩니다. 나는 마지막 부분을 제외하고 모든 것을 할 수 있었다. 항목을 변경할 때마다 회 전자가 자동으로 닫힙니다 (초점을 잃지 않고).
내가 생각한 유일한 해결책은 mSpinner.performClick()
을 사용하여 회 전자를 닫은 후 즉시 열 수 있습니다. 물론 빠른 재연 결과를 얻을 수 있기 때문에 충분하지 않습니다. 쿨하지 않아.
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);
}
}
}
및 사용자 정의 어댑터 :
내가 논리를 관리하는 사용자 정의 스피너 클래스 생성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));
}
}
내 스피너를, 대부분의 작업은 끝에서 private class OnItemSelected
에서 이루어집니다 스 니펫의
처음에 문제는 내 어댑터에서 변환 된 뷰 (처음에는 뷰 패턴을 변환하지 않았 음)로 보았지만 지금은 사용하고있는 것을 볼 수 있습니다.
이 문제는 2 개의 다른 장치와 내 에뮬레이터에서 발생하므로 장치 관련 문제가 아닌 것으로 간주하는 것이 안전합니다.
누구나 아이디어 나 조언이 있으십니까?
그래서 동적 회에서 항목을 추가/삭제 할 수있는 방법은 없습니다? – TheCrafter
@TheCrafter - 추가/삭제하려면 arraylist에서 추가/제거하고 itemSelected() 메소드에서 notifyDataSetChanged()를 호출해야합니다. – Ragini
나는 이미 그렇게하고있다. 실제로 어댑터 데이터 세트를 업데이트하지만 회 전자를 자동으로 닫습니다. 회 전자를 닫지 않고이를 수행 할 방법을 찾고 있습니다. – TheCrafter