在运行时更改适配器

时间:2012-01-11 22:22:56

标签: android listview listadapter

我正在使用适配器按字母顺序在单独的屏幕上显示光标的结果。问题是我需要使用EditText字段来过滤结果。 当我使用过滤器适配器执行此操作时,由于必须重做的每个字母的索引属性,总是会出错。所以我认为只有当用户为搜索字段生成过滤器时,我才会将适配器更改为简单的,不按字母顺序划分。 我保留原始适配器和没有过滤器的适配器来搜索我添加将运行另一个游标的过滤器。这个在运行时交换适配器给出了问题:当我为Y-Adapter更改X Adapter(没有filterqueryprovider)时(使用filterqueryprovider)工作正常..但是当反向为真时,filterqueryprovider只是在X Adapter中运行并且结果为光标没有出现。如何解决这个问题呢?

请参阅适配器和我的活动

下面的代码

适配器:

/**
 * 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) {
    }
};  

}

1 个答案:

答案 0 :(得分:2)

如果您已经设置了适配器,再次设置它不会更新UI。您需要使用adapter.notifyDataSetChanged()

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