addTextChangedListener with listview with subtext

时间:2012-05-14 08:36:45

标签: android listview android-emulator textwatcher

我想搜索列表并再次在列表中显示结果 所以我使用了addtextchangelistener,但找不到一种方法让它与带有子文本的listview一起工作

这是我的代码:

  package com.android;

    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.LineNumberReader;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.StringTokenizer;

    import android.app.ListActivity;
    import android.os.Bundle;
    import android.text.Editable;
    import android.text.TextWatcher;
    import android.util.Log;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.EditText;
    import android.widget.ListView;
    import android.widget.SimpleAdapter;
    import android.widget.TextView;

    public class MyListDemoActivity extends ListActivity {
        /** Called when the activity is first created. */
        TextView tv;



        //** List<String> content;

        EditText actv;
        List<String> arr_sort;
        //** ArrayAdapter<String> adapter;
        SimpleAdapter simpleadapter;
        ListView lv;

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

            String line = " ";

            LineNumberReader linenoreader = null;
            StringTokenizer stringtokanixer = null;
        //**    content = new ArrayList<String>();
            List<Map<String,String>> data= new ArrayList<Map<String,String>>();

            lv = (ListView) findViewById(android.R.id.list);

            try {

                InputStream istream = getResources().openRawResource(R.raw.grelist);
                InputStreamReader streamreader = new InputStreamReader(istream);

                linenoreader = new LineNumberReader(streamreader);
                linenoreader.mark(15);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }// try catch ends here

            Log.v("getting", "working");

            for(int i=0;i<8;i++)
            {
                Map<String,String> datum= new HashMap<String,String>(2);
                try {
                    line = linenoreader.readLine();
                    Log.v("item",line);
                } catch (IOException e) {

                    e.printStackTrace();
                }
                Log.v("getting", line);
                stringtokanixer = new StringTokenizer(line);

                String st = stringtokanixer.nextToken();
                String meaning="";
                while (stringtokanixer.hasMoreTokens()) {
                    meaning +=" " +stringtokanixer.nextToken();

                }// for ends

                // map is used to add word and meaning 
                datum.put("word",st);
                datum.put("meaning",meaning);
                data.add(datum);

                //List<String> is usedto add
        //**        content.add(st);
            }


            simpleadapter = new SimpleAdapter(this, data, android.R.layout.simple_list_item_2, new String[]{"word","meaning"}, new int[]{android.R.id.text1,android.R.id.text2});

            // setListAdapter(adapter);

            lv.setAdapter(simpleadapter);
            tv = (TextView) findViewById(R.id.textView1);

            actv = (EditText) findViewById(R.id.editText1);


            /*  
                actv.addTextChangedListener(new TextWatcher() {
                int len = 0;


                @Override
                public void onTextChanged(CharSequence s, int start, int before,
                        int count) {
                        arr_sort = new ArrayList<String>();

                        len = actv.getText().length();

                        for (int i = 0; i < content.size(); i++) {
                            if (len <= content.get(i).length()) {
                                if (actv.getText()
                                        .toString()
                                        .trim()
                                        .equalsIgnoreCase(
                                                (String) content.get(i).subSequence(0,
                                                        len))) {

                                    arr_sort.add(content.get(i));
                                    Log.v("infor loop afterTextChanged", s.toString());
                                }

                            }

                        }

            //          adapter.notifyDataSetChanged();

                        adapter = new ArrayAdapter<String>(MyListDemoActivity.this,
                            android.R.layout.simple_list_item_1, arr_sort);
                        setListAdapter(adapter);
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count,
                        int after) {
                        Log.v("beforetextchange","hello here");
                }

                @Override
                public void afterTextChanged(Editable s) {
                    Log.v("aftertextchange","hello here");

                }
            }); // text watcher class ends here
    */


        }// on create ends here

        public void onListItemClick(ListView ls, View v, int position, long id) {
            //tv.setText(content.get(position));

            // tv.setText(content[position]) // in case of string

        }// endsd here onListItemClick(
    }

4 个答案:

答案 0 :(得分:4)

我已经回答了两个StackOverflow问题,你可以使用它们,

首先使用android提供的getFilter()使用Filterrable接口过滤到Adapter类。您可以从here查看。

其次是使用外部jar Lambdaj,这是从List中过滤大量数据的最佳和最有效的方法。您也可以从here

查看

答案 1 :(得分:3)

我的理解是: - 您只想过滤ListView。对?

让我知道如果我误解了这个问题!!!

<强> main.xml中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
    android:layout_width="fill_parent" android:layout_height="fill_parent">

    <EditText android:id="@+id/search" android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:inputType="text" />

    <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" />

</LinearLayout>

<强> ListViewSearchActivity

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class ListViewSearchActivity extends Activity implements TextWatcher {

    private SimpleAdapter simpleAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        EditText search = (EditText) findViewById(R.id.search);
        search.addTextChangedListener(this);

        List<Map<String, String>> data = new ArrayList<Map<String, String>>();
        for(int i=0;i<8;i++) {
            Map<String,String> map = new HashMap<String, String>(2);
            map.put("word", "word " + i);
            map.put("meaning", "meaning " + (i + 10));
            data.add(map);
        }

        ListView listView = (ListView) findViewById(R.id.list);
        this.simpleAdapter = new SimpleAdapter(this, data, android.R.layout.simple_list_item_2, new String[]{"word","meaning"}, new int[]{android.R.id.text1,android.R.id.text2});
        listView.setAdapter(this.simpleAdapter);
    }

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

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        this.simpleAdapter.getFilter().filter(s.toString());
    }

}

答案 2 :(得分:2)

以下是我如何更改代码以使其正常工作:

1。我会删除arr_sort变量,并添加其他ArrayList Maps来保存过滤后的值:

//  List<String> arr_sort;
    final ArrayList<Map<String, String>> data = 
        new ArrayList<Map<String, String>>();
    final ArrayList<Map<String, String>> filteredData = 
        new ArrayList<Map<String, String>>();

我也会让它们成为最终版,因为在我们修改内容时,没有必要为它们分配全新的值。

2。 simpleadapter应始终显示已过滤的数据,因此必须进行修改:

filteredData.addAll(data); // fill up filteredData initially with the whole list
simpleadapter = new SimpleAdapter(this, filteredData, 
        android.R.layout.simple_list_item_2, 
        new String[] { "word", "meaning" }, 
        new int[] {android.R.id.text1, android.R.id.text2 });

3. 接下来,我将过滤代码从onTextChanged方法移至afterTextChanged方法,以根据输入的整个文本执行过滤。使用Regexp也比所有String操作(+,substring ...)

消耗更少的资源

这样您的TextWatcher实现就像:

actv.addTextChangedListener(new TextWatcher()
{
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count)
    {}

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

    @Override
    public void afterTextChanged(Editable s)
    {
        Log.v("MLDA", "afterTextChanged");
        // a temporary source list for better performance:
        // if it's possible, use the smaller filtered list
        final ArrayList<Map<String, String>> tmpSource = 
            new ArrayList<Map<String,String>>();
        tmpSource.addAll(
            (filterText.length() > 0 && s.toString().contains(filterText)) 
            ? filteredData : data);
        filterText = s.toString();

        // a temporary result list to fill with the filtered data
        final ArrayList<Map<String, String>> tmpResult = 
            new ArrayList<Map<String,String>>();

        if (filterText.length() == 0)
            tmpResult.addAll(data); //if no filter, return the base data
        else
        {
            final Pattern pattern = 
                Pattern.compile("(?i)" + Pattern.quote(s.toString()));
            Matcher matcher;
            for (final Map<String, String> map : tmpSource)
            {
                //first match against the "word":
                matcher = pattern.matcher(map.get("word"));
                if (!matcher.find())
                {
                    //if no matches were found, try to match the "meaning"
                    matcher = pattern.matcher(map.get("meaning"));
                    if (!matcher.find())
                        continue; //if no match, move to the next map
                }
                tmpResult.add(map); //match found: add to new list
            }
        }

        filteredData.clear();
        filteredData.addAll(tmpResult);
        simpleadapter.notifyDataSetChanged(); // update display
    }
});

使用临时列表可以在没有gui更新的情况下构建整个过滤数据(如果直接删除/添加项目到filteredData列表,适配器将触发更新方法)。

另请注意,通过检查新过滤器文本是否包含旧过滤器文本,我们可以使用当前filteredData列表作为源。

同样,如果filterText是一个空字符串,则没有必要执行任何匹配,我们只需返回base列表即可。

答案 3 :(得分:1)

ArrayList<String> tempList ;
edtText.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // TODO Auto-generated method stub
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable s) {
                // TODO Auto-generated method stub
                if (!edtText.getText().toString().equalsIgnoreCase("")){
                    tempList = new ArrayList<String>();
                    tempList.clear();
                    String text = filterText.getText().toString();
                    for(int i=0 ;i< listname.size();i++){
                        //if(globalconstant.mosq_list.get(globalconstant.hashformosq.get(globalconstant.tempList.get(i))).name.toUpperCase().toString().contains(text.toUpperCase())){
                        if(listname.get(i).toUpperCase().toString().contains(text.toUpperCase())){
                            tempList.add(listname.get(i));
                        }
                    }
                 used changed tempList
                }else{

                    unchaged tempList
                }
            }
        });
    }