簡體   English   中英

ArrayAdapter和搜索功能有問題嗎?

[英]Bug with ArrayAdapter and Search function?

當我在名稱列表中搜索值時,它將返回相應的值。 但是,當我刪除該值時,我的ListView不再再次返回列表中的所有名稱,它們消失了。 如何解決呢? 任何想法?

TabelaActivity.java代碼:

package com.akzonobel.malote.tabela;

import com.akzonobel.malote.R;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.ListView;

/*
 * Very basic Activity, the only things it does
 * are get the ListView reference from our layout.
 * Create an Adapter, set the Adapter to the ListView
 * and handle the onItemClick events for when the user
 * clicks on a row.
 */
public class TabelaActivity extends Activity {
    EditText inputSearch;
    CSVAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tabela);

        //Lookup our ListView
        ListView mList = (ListView)findViewById(R.id.mList);
        inputSearch = (EditText) findViewById(R.id.inputSearch);
        //Create Adapter. The second parameter is required by ArrayAdapter
        //which our Adapter extends. In this example though it is unused,
        //so we'll pass it a "dummy" value of -1.
        mAdapter = new CSVAdapter(this, -1);

        //attach our Adapter to the ListView. This will populate all of the rows.
        mList.setAdapter(mAdapter);


        /*
         * This listener will get a callback whenever the user clicks on a row. 
         * The pos parameter will tell us which row got clicked.
         * 
         * For now we'll just show a Toast with the state capital for the state that was clicked.
         */
        inputSearch.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                // When user changed the Text
                TabelaActivity.this.mAdapter.getFilter().filter(cs);  
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub                          
            }
        });
    }

    }

CSVAdapter.java代碼:

package com.akzonobel.malote.tabela;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;


/*
 * Very basic Custom Adapter that takes state name,capital pairs out of a csv
 * file from the assets and uses those values to build a List of State objects.
 * Overrides the default getView() method to return a TextView with the state name.
 * 
 * ArrayAdapter - a type of Adapter that works a lot like ArrayList.
 */
@SuppressLint("DefaultLocale") public class CSVAdapter extends ArrayAdapter<State>{
    private List<State> filteredModelItemsArray;
    private Filter filter;
    Context ctx;

    //We must accept the textViewResourceId parameter, but it will be unused
    //for the purposes of this example.
    public CSVAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);

        //Store a reference to the Context so we can use it to load a file from Assets.
        this.ctx = context;

        //Load the data.
        loadArrayFromFile();
    }
    @Override
    public Filter getFilter() {
        if (filter == null){
          filter  = new ModelFilter();
        }
        return filter;
      }


    /*
     * getView() is the method responsible for building a View out of a some data that represents
     * one row within the ListView. For this example our row will be a single TextView that
     * gets populated with the state name.
     * (non-Javadoc)
     * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
     */

    @Override
    public View getView(final int pos, View convertView, final ViewGroup parent){
        /*
         * Using convertView is important. The system will pass back Views that have been
         * created but scrolled off of the top (or bottom) of the screen, and thus are no
         * longer being shown on the screen. Since they are unused, we can "recycle" them
         * instead of creating a new View object for every row, which would be wasteful, 
         * and lead to poor performance. The diference may not be noticeable in this
         * small example. But with larger more complex projects it will make a significant
         * improvement by recycling Views rather than creating new ones for each row.
         */
        TextView mView = (TextView)convertView;
        //If convertView was null then we have to create a new TextView.
        //If it was not null then we'll re-use it by setting the appropriate
        //text String to it.
        if(null == mView){ 
            mView = new TextView(parent.getContext());
            mView.setTextSize(19);
            mView.setTextColor(Color.WHITE);
        }

        //Set the state name as the text.
        mView.setText(getItem(pos).getName());

        //We could handle the row clicks from here. But instead
        //we'll use the ListView.OnItemClickListener from inside
        //of MainActivity, which provides some benefits over doing it here.
        return mView;
    }

    /*
     * Helper method that loads the data from the states.csv and builds
     * each csv row into a State object which then gets added to the Adapter.
     */
    private void loadArrayFromFile(){
        try {
            // Get input stream and Buffered Reader for our data file.
            InputStream is = ctx.getAssets().open("states.csv"); 
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;

            //Read each line
            while ((line = reader.readLine()) != null) {


                //Create a State object for this row's data.
                State cur = new State();
                cur.setName(line);

                //Add the State object to the ArrayList (in this case we are the ArrayList).
                this.add(cur);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class ModelFilter extends Filter
    {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            constraint = constraint.toString().toLowerCase();
            FilterResults result = new FilterResults();
            if(constraint != null && constraint.toString().length() > 0)
            {
                ArrayList<State> filteredItems = new ArrayList<State>();

                for(int i = 0, l = getCount(); i < l; i++)
                {
                    State m = getItem(i);
                    if(m.getName().toLowerCase().contains(constraint))
                        filteredItems.add(m);
                }
                result.count = filteredItems.size();
                result.values = filteredItems;
            }
            else
            {
                ArrayList<State> allItems = new ArrayList<State>();
                for(int i = 0, l = getCount(); i < l; i++)
                {
                    State m = getItem(i);
                    allItems.add(m);
                }
                synchronized(this)
                {
                    result.values = allItems;
                    result.count = allItems.size();
                }
            }
            return result;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            filteredModelItemsArray = (ArrayList<State>)results.values;
            notifyDataSetChanged();
            clear();
            for(int i = 0, l = filteredModelItemsArray.size(); i < l; i++)
                add(filteredModelItemsArray.get(i));
            notifyDataSetInvalidated();
        }
    }
    }

State.java代碼:

package com.akzonobel.malote.tabela;


/*
 * Basic Data class to hold a state name and the state capital.
 */
public class State {

    private String name;


    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

這是一個相當老的錯誤,Android從未解決過。 它首先在此處報道, 發行號為9666 ,然后關閉並重新開放為發行號69179 我不會在任何時候都屏住呼吸。 如果您想了解更多有關原因的詳細信息,我寫了一篇小博文談論它。

或多或少,如果您要過濾數據並添加,刪除,更新等部分數據,則需要擴展BaseAdapter並編寫自己的解決方案。 或者節省一些時間,並利用我的挫敗感反復進行多次,而我只是將所有這些都扔進了一個開源庫中。 解決所有的過濾錯誤,然后解決一些: Advanced-Adapters

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM