1

"ClassName"문자열 속성 ("Warrior", "Hunter", "Assassin"등)이있는 80 개 이상의 "God"개체 목록이있는 Android 앱을 개발 중입니다.).ToggleButton 필터가있는 ListView 어댑터

ClassName으로 목록을 필터링하는 ToggleButtons를 구현하려고합니다. 한 번에 여러 개의 필터를 사용할 수 있습니다 (예 : "Warrior"및 "Hunter"ToggleButtons가 ClassName "Warrior"또는 "Hunter"가있는 모든 객체를 표시해야 함)를 확인하십시오.

지금까지 한 ClassName 제약 조건을 기반으로 목록을 필터링 할 수만있었습니다. 이 일을 성취하는데 도움이된다면 크게 감사하겠습니다! 여기

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View myView = inflater.inflate(R.layout.home,null); 

     final ArrayList<God> gods = getGods(); 

     lv = (ListView) myView.findViewById(R.id.home_list); 
     sv = (SearchView) myView.findViewById(R.id.home_search); 
     sv.setQueryHint("Search Gods..."); 
     mage = (ToggleButton) myView.findViewById(R.id.mage); 
     assassin = (Button) myView.findViewById(R.id.assassin); 

     adapter = new GodAdapter(getActivity(), gods); 
     lv.setAdapter(adapter); 

     mage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       if(isChecked){ 
        //Include all mages 
       } 
       else { 
        //Remove all mages 

       } 
      } 
     }); 

assassin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
       @Override 
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
        if(isChecked){ 
         //Include all assassins 
        } 
        else { 
         //Remove all assassins 

        } 
       } 
      }); 

(...other buttons...) 



     sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 
      public boolean onQueryTextSubmit(String query) { 
       return false; 
      } 
      public boolean onQueryTextChange(String query) { 
       adapter.getFilter().filter(query); 
       return false; 
      } 
     }); 

     lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { 
       String name = adapter.getItem(position).getName(); 

       for(int i = 0; i < gods.size(); i++) { 
        if(gods.get(i).getName().equals(name)) 
        { 
         Fragment myFragment = new TabFragment(); 
         myFragment.setArguments(createGodBundle(gods.get(i))); 
         replaceFragment(myFragment); 
         hideSoftKeyboard(getActivity()); 
         break; 
        } 
       } 
      } 
     }); 

     return myView; 
    } 

그리고 내 GodAdapter입니다 :

public class GodAdapter extends BaseAdapter implements Filterable { 

    Context c; 
    ArrayList<God> gods; 
    ArrayList<God> filterList; 
    CustomFilter filter; 

    public GodAdapter(Context c, ArrayList<God> gods) { 
     this.c = c; 
     this.gods = gods; 
     this.filterList = gods; 
    } 

    public int getCount() { 
     return gods.size(); 
    } 

    public God getItem(int position) { 
     return gods.get(position); 
    } 

    public long getItemId(int position) { 
     return gods.indexOf(getItem(position)); 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 


     LayoutInflater inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     if(convertView == null) 
      convertView = inflater.inflate(R.layout.god_selection, null); 

     TextView name = (TextView) convertView.findViewById(R.id.god_name); 
     ImageView image = (ImageView) convertView.findViewById(R.id.god_image); 
     ImageView pantheon =(ImageView) convertView.findViewById(R.id.pantheon); 
     ImageView type =(ImageView) convertView.findViewById(R.id.type); 

     name.setText(gods.get(position).getName()); 
     image.setImageResource(gods.get(position).getImage()); 
     pantheon.setImageResource(gods.get(position).getPantheonIcon()); 
     type.setImageResource(gods.get(position).getClassIcon()); 

     return convertView; 
    } 

    public Filter getFilter() { 
     if(filter == null) 
      filter = new CustomFilter(); 
     return filter; 
    } 


    //Inner class for filtering 
    class CustomFilter extends Filter { 

     protected FilterResults performFiltering(CharSequence constraint) { 

      FilterResults results = new FilterResults(); 

      if(constraint != null && constraint.length() > 0) 
      { 
       constraint = constraint.toString().toUpperCase(); 
       ArrayList<God> filters = new ArrayList<God>(); 

       for(int i = 0; i < filterList.size(); i++) 
       { 
        if(filterList.get(i).getName().toUpperCase().contains(constraint)) 
        { 
         God god = new God(filterList.get(i).getName(), filterList.get(i).getTitle(), filterList.get(i).getNameString(), filterList.get(i).getImage(), 
           filterList.get(i).getPantheon(), filterList.get(i).getPantheonIcon(), filterList.get(i).getClassName(), filterList.get(i).getClassIcon(), filterList.get(i).getType(), 
           filterList.get(i).getHealth(), filterList.get(i).getMana(), filterList.get(i).getDamage(), filterList.get(i).getProtPhys(), filterList.get(i).getProtMag(), filterList.get(i).getSpeed(), 
           filterList.get(i).getHp5(), filterList.get(i).getMp5(), filterList.get(i).getAttackSpeed()); 
         filters.add(god); 
        } 
       } 
       results.count = filters.size(); 
       results.values = filters; 
      } else { 
       results.count = filterList.size(); 
       results.values = filterList; 
      } 
      return results; 
     } 

     protected void publishResults(CharSequence constraint, FilterResults results) { 
      gods = (ArrayList<God>) results.values; 
      notifyDataSetChanged(); 
     } 
    } 

} 

답변

1

내가 Adapter에서 모든 필터의 ArrayList를 유지하여이 문제를 해결이

여기 내 주요 조각입니다.

이 경우 ArrayList이 제약 조건이므로 God의 클래스가 포함되어 있는지 확인하여 요소를 필터링 할 수 있습니다.


예 :

public class GodAdapter extends BaseAdapter implements Filterable { 

    ... 
    ArrayList<God> gods; 
    ArrayList<God> filteredGods; 
    private ArrayList<String> classFilters; 

    ... 

    public boolean toggleFilter(String class) { 
     if (classFilters.contains(class)) { 
      classFilters.remove(class); 
      return false; 
     } else { 
      classFilters.add(class); 
      return true; 
     } 
    } 

    ... 

    class CustomFilter extends Filter { 

     protected FilterResults performFiltering(CharSequence constraint) { 

      FilterResults results = new FilterResults(); 

      if(classFilters.size() > 0){ 
       ArrayList<God> filteredList = new ArrayList<God>(); 

       for(int i = 0; i < filterList.size(); i++){ 
        God god = filterList.get(i); 
        if(classFilters.contains(god.getName().toUpperCase())){ 
         filteredList.add(god); 
        } 
       } 
       results.count = filteredList.size(); 
       results.values = filteredList; 
      } else { 
       results.count = filterList.size(); 
       results.values = filterList; 
      } 
      return results; 
     } 

     protected void publishResults(CharSequence constraint, FilterResults results) { 
      // IMPORTANT publish the results to a separate list 
      filteredGods = (ArrayList<God>) results.values; 
      notifyDataSetChanged(); 
     } 
} 

내가 God 클래스 대신 String들에 대해 설명하는 enum 사용하는 것이 좋습니다 것입니다. 이 질문에서 너무 멀리 떨어져있는 이유를 설명하면 but you can read about it here입니다.

나는 모든 데이터 배열을 가지고 : 나는 비슷한 situatios을 위해 무슨 짓을

+0

내 문제가 해결되었습니다. 도와 줘서 고마워. –

1

다음이다. 그러나 listview를 채우기 위해 첫 번째 배열을 필터링하여 두 번째 배열을 생성합니다.

필터의 경우 비 독점 키 조합을 사용합니다.

public static fianl STATUS_WARRIOR = 1; //binary: 00000001 
public static fianl STATUS_HUNTER = 2; //binary: 00000010 
public static fianl STATUS_ASSASIN = 4; //binary: 00000100 

무기의 각 인스턴스에 대해 상태는이 세 가지 중 하나가됩니다.

토글을 기반으로하는 필터 클리테리아는이 세 가지 값의 조합 일 수 있습니다.

예 : 전사와 어쌔신 : 00000101 헌터 어쌔신 : 00000110

이 (당신은 단지 '|' 필요 (또는) 활성 값)

그래서 토글이 0에서 7 사이의 숫자를 정의합니다

필터링을 위해서는 무기의 상태를 확인하기 만하면됩니다. '&' (and) 필터 creteria. 0이 아닌 경우 listview에 전달할 배열을 포함시킵니다.

private ArrayList<Weapon> allWeaponsArrayList = new ArrayList<>(); 

// Set all the weapons perhaps in onCreate() inside allWeaponsArrayList. 

int statusFromToggles = 0; 
statusFromToggles = toggleWarriorOn? statusFromToggles | STATUS_WARRIOR: statusFromToggles ; 
statusFromToggles = toggleHunterOn? statusFromToggles | STATUS_HUNTER: statusFromToggles ; 
statusFromToggles = toggleAssasinOn? statusFromToggles | STATUS_ASSASIN: statusFromToggles ; 

public ArrayList<Weapon> filterWeapons(statusFromToggles){ 
    ArrayList<Weapon> rtn = new ArrayList<Weapon>(); 
    for(Weapon weapon : allWeaponsArrayList){ 
     if(weapon.getStatus() & statusFromToggles){ 
      rtn.add(weapon); 
     } 
    } 
    return rtn; 
} 

면책 조항 : 일부 오타가있을 수 있으므로 코드를 실행하지 않았습니다. 그렇다면 알려 주시면 확인하겠습니다. 그러나 여전히 아이디어를 얻을 수 있습니다.

+0

나는 이진 연산을 좋아한다. 질문에서와 같이'BaseAdapter'에서 실제'Filter'를 사용하여 답을 확장 할 수 있습니다. 제약 조건으로 Integer.toBinaryString (int i);을 사용하여 필터 정수를 String으로 전달한 다음 Integer.parseInt (constraint, 2);를 사용하여 필터에서 구문 분석 할 수 있습니다. – Barthy

+0

@Barthy, 필자는 필터 사용에 동의하지만 바이너리 변환을 피하고 기수 10의 모든 것을 처리 할 수 ​​있습니다. – Juan

+0

하지만 여전히'String' /'CharSequence'를 구문 분석해야합니다. 맞습니까? – Barthy