2012-01-11 79 views
1

我正在使用适配器以按字母顺序在单独的屏幕上显示游标的结果。问题是我需要使用EditText字段来过滤结果。 当我这样做与过滤器适配器总是给出错误,由于每个字母的索引属性,他必须重做字母。所以我认为只有当用户为搜索字段设置了过滤器时,才会将适配器更改为简单的无字母分割。 我离开原来的适配器和适配器没有过滤器来搜索我添加将运行另一个游标的过滤器。在运行时交换适配器给定的问题:当我更改X适配器(无filterqueryprovider)的Y适配器(与filterqueryprovider)工作正常..但是当相反是真正的filterqueryprovider只是运行在X适配器和结果光标不会出现。如何解决这个问题呢?在运行时更改适配器

查看适配器下面的代码和我的活动

适配器:

/** 
* CursorAdapter that uses an AlphabetIndexer widget to keep track of the section indicies. 
* These are the positions where we want to show a section header showing the respective alphabet letter. 
* @author Eric 
* 
*/ 
public class OrdemAlfabeticaAdapter extends SimpleCursorAdapter implements SectionIndexer{ 

private static final int TYPE_HEADER = 1; 
private static final int TYPE_NORMAL = 0; 

private static final int TYPE_COUNT = 2; 

private AlphabetIndexer indexer; 

private int[] usedSectionNumbers; 

private Map<Integer, Integer> sectionToOffset; 
private Map<Integer, Integer> sectionToPosition; 
private Context context; 

public OrdemAlfabeticaAdapter(Context context, int layout, Cursor c, String coluna, 
     String[] from, int[] to) { 
    super(context, layout, c, from, to); 

    this.context = context; 

    indexer = new AlphabetIndexer(c, c.getColumnIndexOrThrow(coluna), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 
    sectionToPosition = new TreeMap<Integer, Integer>(); //use a TreeMap because we are going to iterate over its keys in sorted order 
    sectionToOffset = new HashMap<Integer, Integer>(); 

    final int count = super.getCount(); 

    int i; 
    //temporarily have a map alphabet section to first index it appears 
    //(this map is going to be doing somethine else later) 
    for (i = count - 1 ; i >= 0; i--){ 
     sectionToPosition.put(indexer.getSectionForPosition(i), i); 
    } 

    i = 0; 
    usedSectionNumbers = new int[sectionToPosition.keySet().size()]; 

    //note that for each section that appears before a position, we must offset our 
    //indices by 1, to make room for an alphabetical header in our list 
    for (Integer section : sectionToPosition.keySet()){ 
     sectionToOffset.put(section, i); 
     usedSectionNumbers[i] = section; 
     i++; 
    } 

    //use offset to map the alphabet sections to their actual indicies in the list 
    for(Integer section: sectionToPosition.keySet()){ 
     sectionToPosition.put(section, sectionToPosition.get(section) + sectionToOffset.get(section)); 
    } 

} 

@Override 
public int getCount() { 
    if (super.getCount() != 0){ 
     //sometimes your data set gets invalidated. In this case getCount() 
     //should return 0 and not our adjusted count for the headers. 
     //The only way to know if data is invalidated is to check if 
     //super.getCount() is 0. 
     return super.getCount() + usedSectionNumbers.length; 
    } 

    return 0; 
} 

@Override 
public Object getItem(int position) { 
    if (getItemViewType(position) == TYPE_NORMAL){//we define this function in the full code later 
     //if the list item is not a header, then we fetch the data set item with the same position 
     //off-setted by the number of headers that appear before the item in the list 
     return super.getItem(position - sectionToOffset.get(getSectionForPosition(position)) - 1); 
    } 

    return null; 
} 

@Override 
public int getPositionForSection(int section) { 
    if (! sectionToOffset.containsKey(section)){ 
     //This is only the case when the FastScroller is scrolling, 
     //and so this section doesn't appear in our data set. The implementation 
     //of Fastscroller requires that missing sections have the same index as the 
     //beginning of the next non-missing section (or the end of the the list if 
     //if the rest of the sections are missing). 
     //So, in pictorial example, the sections D and E would appear at position 9 
     //and G to Z appear in position 11. 
     int i = 0; 
     int maxLength = usedSectionNumbers.length; 

     //linear scan over the sections (constant number of these) that appear in the 
     //data set to find the first used section that is greater than the given section, so in the 
     //example D and E correspond to F 
     while (i < maxLength && section > usedSectionNumbers[i]){ 
      i++; 
     } 
     if (i == maxLength) return getCount(); //the given section is past all our data 

     return indexer.getPositionForSection(usedSectionNumbers[i]) + sectionToOffset.get(usedSectionNumbers[i]); 
    } 

    return indexer.getPositionForSection(section) + sectionToOffset.get(section); 
} 

@Override 
public int getSectionForPosition(int position) { 
    int i = 0;  
    int maxLength = usedSectionNumbers.length; 

    //linear scan over the used alphabetical sections' positions 
    //to find where the given section fits in 
    while (i < maxLength && position >= sectionToPosition.get(usedSectionNumbers[i])){ 
     i++; 
    } 
    return usedSectionNumbers[i-1]; 
} 

@Override 
public Object[] getSections() { 
    return indexer.getSections(); 
} 
//nothing much to this: headers have positions that the sectionIndexer manages. 
@Override 
public int getItemViewType(int position) { 
    if (position == getPositionForSection(getSectionForPosition(position))){ 
     return TYPE_HEADER; 
    } 
    return TYPE_NORMAL; 
} 

@Override 
public int getViewTypeCount() { 
    return TYPE_COUNT; 
} 

//return the header view, if it's in a section header position 
@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    final int type = getItemViewType(position); 
    if (type == TYPE_HEADER){ 
     if (convertView == null){ 
      LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
//    convertView = getLayoutInflater().inflate(R.layout.header, parent, false); 
      convertView = inflater.inflate(R.layout.cabecalho_divisao_alfabetica, parent, false); 
     } 
     ((TextView)convertView.findViewById(R.id.header)).setText((String)getSections()[getSectionForPosition(position)]); 
     return convertView; 
    } 
    return super.getView(position - sectionToOffset.get(getSectionForPosition(position)) - 1, convertView, parent); 
} 


//these two methods just disable the headers 
@Override 
public boolean areAllItemsEnabled() { 
    return false; 
} 

@Override 
public boolean isEnabled(int position) { 
    if (getItemViewType(position) == TYPE_HEADER){ 
     return false; 
    } 
    return true; 
} 

public AlphabetIndexer getIndexer() { 
    return indexer; 
} 

} 

我的活动:

public class BuscaProprietarioActivity extends ListActivity { 

private SimpleCursorAdapter adapter1; 
private SimpleCursorAdapter adapter2; 
private EditText filterEditText; 
private LinearLayout viewNenhumRegistroEncontrado; 
private LinearLayout viewResultado; 
private final String[] colunas = new String[] { ProprietarioProvider.Columns.ID, 
     ProprietarioProvider.Columns.NOME, ProprietarioProvider.Columns.TELEFONE }; 
private Cursor cursor; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.proprietario_busca); 

    filterEditText = (EditText) findViewById(R.id.busca_proprietario_campo_busca); 
    ContentResolver cr = getContentResolver(); 

    Intent intent = getIntent(); 
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) { 
     String query = intent.getStringExtra(SearchManager.QUERY); 
     String s = "'%" + query + "%'"; 
     String selection = ProprietarioProvider.Columns.NOME + " LIKE " + s; 
     cursor = cr.query(ProprietarioProvider.CONTENT_URI, colunas, selection, null, 
       ProprietarioProvider.Columns.NOME + " COLLATE LOCALIZED ASC"); 
    } else { 
     cursor = cr.query(ProprietarioProvider.CONTENT_URI, colunas, null, null, 
       ProprietarioProvider.Columns.NOME + " COLLATE LOCALIZED ASC"); 
    } 


    if (cursor.moveToNext()) { 
     viewResultado = (LinearLayout) findViewById(R.id.busca_proprietario_resultado); 
     viewResultado.setVisibility(View.VISIBLE); 

     adapter1 = new OrdemAlfabeticaAdapter(this, R.layout.list_item_proprietario, 
       cursor, ProprietarioProvider.Columns.NOME, new String[]{ProprietarioProvider.Columns.NOME, 
       ProprietarioProvider.Columns.TELEFONE}, 
       new int[]{R.id.list_item_proprietario_nome, R.id.list_item_proprietario_telefone}); 
     setListAdapter(adapter1); 

     adapter2 = new SimpleCursorAdapter(getApplicationContext(), 
       R.layout.list_item_proprietario, cursor, new String[]{ProprietarioProvider.Columns.NOME, 
      ProprietarioProvider.Columns.TELEFONE}, 
      new int[]{R.id.list_item_proprietario_nome, R.id.list_item_proprietario_telefone}); 
     adapter2.setFilterQueryProvider(filterQueryProvider); 

     filterEditText = (EditText) findViewById(R.id.busca_proprietario_campo_busca); 
     filterEditText.addTextChangedListener(filterTextWatcher); 



    } else { 
     // mostra tela de registro nao encontrado 
     viewNenhumRegistroEncontrado = (LinearLayout) findViewById(R.id.busca_proprietario_nenhum_registro_encontrado); 
     viewNenhumRegistroEncontrado.setVisibility(View.VISIBLE); 
    } 

} 

private FilterQueryProvider filterQueryProvider = new FilterQueryProvider() { 
    public Cursor runQuery(CharSequence constraint) { 
     String selection = ProprietarioProvider.Columns.NOME + " LIKE '"+constraint+"%'"; 
     cursor = getContentResolver().query(ProprietarioProvider.CONTENT_URI, colunas, selection, null, 
       ProprietarioProvider.Columns.NOME + " COLLATE LOCALIZED ASC"); 

     return cursor; 
    } 
}; 

private TextWatcher filterTextWatcher = new TextWatcher() { 

    @Override 
    public void onTextChanged(CharSequence s, int start, int before, 
      int count) { 
     if (s != null && s.length() > 0) { 
      setListAdapter(adapter2); 
      getListView().setTextFilterEnabled(true); 
      adapter2.getFilter().filter(s.toString()); 
      getListView().setFastScrollEnabled(false); 
     } else { 
      setListAdapter(adapter1); 
      getListView().setFastScrollEnabled(true); 
     } 
    } 

    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, 
      int after) { 
    } 

    @Override 
    public void afterTextChanged(Editable s) { 
    } 
}; 

} 

回答

2

如果你已经设置你的适配器,再设置不会更新UI。你将需要使用adapter.notifyDataSetChanged()

https://stackoverflow.com/a/7920243/563306

+0

dcanh121,我尝试使用notifyDataSetChanged(),但没有奏效。从adapter2返回到adapter1时,视图不显示任何内容。 – 2012-01-11 23:29:37

+0

已解决。问题在于我在两个适配器中使用了相同的Cursor对象。我刚刚创建了一个新的Cursor对象到Adapter2。 =] – 2012-01-12 00:29:13