2017-02-22 1 views
0

회 전자에 "추가"버튼을 구현하려고합니다. 기본적으로 몇 가지 항목 만 표시하고 마지막 항목 ("자세히 ...")을 클릭하면 회 전자가 변경되어 모든 항목을 표시합니다.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 개의 다른 장치와 내 에뮬레이터에서 발생하므로 장치 관련 문제가 아닌 것으로 간주하는 것이 안전합니다.

누구나 아이디어 나 조언이 있으십니까?

답변

1

MultiSelectListview 및 기타 버튼으로 사용자 정의 대화 상자를 만들어야합니다. 더 많은 버튼을 클릭하면 모든 요소를 ​​Listview에 추가하고 notifyDataSetChanged() 메소드를 호출해야합니다.

+0

그래서 동적 회에서 항목을 추가/삭제 할 수있는 방법은 없습니다? – TheCrafter

+1

@TheCrafter - 추가/삭제하려면 arraylist에서 추가/제거하고 itemSelected() 메소드에서 notifyDataSetChanged()를 호출해야합니다. – Ragini

+0

나는 이미 그렇게하고있다. 실제로 어댑터 데이터 세트를 업데이트하지만 회 전자를 자동으로 닫습니다. 회 전자를 닫지 않고이를 수행 할 방법을 찾고 있습니다. – TheCrafter

1

기본 회 전자는 "기타"항목을로드하는 간단한 방법이 될 수 없습니다. 그러나 "More (추가)"버튼에는 아무런 의미가 없습니다. 30-50 개의 항목이있는 경우 모두 Spinner에로드하십시오. 50-150 개의 항목은 Spinner를 기반으로하는 자체 ListBox/RecyclerView를 사용합니다. 150 개 이상의 항목이 너무 많은 사용자는 하드 한 검색에 필요한 항목이 하나 있습니다. 마지막으로 "검색"기능을 추가하는 것이 유용합니다. 아이디어를 얻으려면 MultiSelect Spinner을 참조하십시오.

enter image description here

+0

그것은 당신에게 이해가되지 않을 수도 있지만 그것은 내 프로젝트 매니저에게 완벽한 의미가 있습니다. 나는 여전히 다른 옵션을 검토하기 전에 회 전자와 함께 작동 할 수있는 방법을 찾고 있습니다. github 프로젝트를 공유해 주셔서 감사합니다! – TheCrafter

+0

@TheCrafter, 자신의 PM을위한 자체 솔루션 제안 –

+0

어떤 방법 으로든 MultiSelect Spinner 자신 만의 Spinner를위한 훌륭한 샘플 –