Android - 将搜索栏添加到自定义列表视图和简单适配器

Posted

技术标签:

【中文标题】Android - 将搜索栏添加到自定义列表视图和简单适配器【英文标题】:Android - Adding search-bar to custom-list-view & simple adaptor 【发布时间】:2017-11-23 20:22:21 【问题描述】:

我尝试使用HashMaps 的Array 创建自定义ListView 和填充值。 UI 显示正常:

但每当在搜索框中输入任何内容时,应用都会关闭并显示Unfortunately app is stopped

我搜索了很多,但无法完成。

也许我尝试应用过滤器的方法是错误的?

代码如下:

public class MyCustomListView extends ListActivity 
    SimpleAdapter adapter;
    EditText inputSearch;

    static final ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_list_view);
        inputSearch = (EditText) findViewById(R.id.search);

        ImageView si = (ImageView) findViewById(R.id.search_icon);
        si.setImageResource(R.drawable.blue_search);

        adapter = new SimpleAdapter(
                this,
                list,
                R.layout.custom_row_view,
                new String[] "img","name","dob","anniversary",
                new int[] R.id.image,R.id.text1,R.id.text2, R.id.text3
        );

        try
            getItemFromXMLandPopulateList(this); // gets the complete list
         catch (Exception e)
            Toast.makeText(this, "Error:\n" + e, Toast.LENGTH_LONG).show();
        

        setListAdapter(adapter);

        // Capture Text in EditText
        inputSearch.addTextChangedListener(new TextWatcher() 
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) 
                adapter.getFilter().filter(s);
            

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

            @Override
            public void afterTextChanged(Editable s) 
            
        );
    

    private void getItemFromXMLandPopulateList(Activity activity) throws XmlPullParserException, IOException 
        Resources res = activity.getResources();
        XmlResourceParser xpp = res.getXml(R.xml.db);
        String id=null, name=null, dob=null, anniversary=null;
        xpp.next();
        int eventType = xpp.getEventType();

        while (eventType != XmlPullParser.END_DOCUMENT)
            switch(eventType)
                case XmlPullParser.START_TAG:
                    String tagname = xpp.getName();
                    if(tagname.equals("ID"))
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) 
                            id = xpp.getText();
                        
                     else if(tagname.equals("Name"))
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) 
                            name = xpp.getText();
                        
                     else if(tagname.equals("DOB"))
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) 
                            dob = xpp.getText();
                        
                     else if(tagname.equals("Anniversary"))
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) 
                            anniversary = xpp.getText();
                        
                    
                    break;
                case XmlPullParser.END_TAG:
                    if(xpp.getName().equals("F"))
                        // Adding 3 value hash to array-list
                        HashMap<String,String> temp = new HashMap<String,String>();
                        temp.put("img", Integer.toString(R.mipmap.profile));
                        temp.put("id", id);
                        temp.put("name", name);
                        temp.put("dob", dob);
                        temp.put("anniversary", anniversary);
                        list.add(temp);
                        // Clearing values for next set
                        id=""; name = ""; dob = ""; anniversary = "";
                    
                    break;
                default:
                    break;
            
            eventType = xpp.next();
        
    

    protected void onListItemClick(ListView l, View v, int position, long id) 
        super.onListItemClick(l, v, position, id);
        HashMap<String, String> item = (HashMap<String, String>) getListAdapter().getItem(position);
        String xmlFile = "r" + item.get("id");
        String name = item.get("name");
        //Toast.makeText(this, "Showing details of: " + name, Toast.LENGTH_LONG).show();

        Intent intent = new Intent(this, ShowDetails.class);
        intent.putExtra("xml", xmlFile);
        startActivity(intent);
    

下面粘贴的崩溃日志,好像是NullPointerException,但不知道如何解决。

I/ActivityManager( 1596): Displayed com.karthikhiraskar.samplesqlitedb/.MyCustomListView: +237ms
W/Filter  (10785): An exception occured during performFiltering()!
W/Filter  (10785): java.lang.NullPointerException
W/Filter  (10785):  at android.widget.SimpleAdapter$SimpleFilter.performFiltering(SimpleAdapter.java:354)
W/Filter  (10785):  at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
W/Filter  (10785):  at android.os.Handler.dispatchMessage(Handler.java:102)
W/Filter  (10785):  at android.os.Looper.loop(Looper.java:136)
W/Filter  (10785):  at android.os.HandlerThread.run(HandlerThread.java:61)
I/LatinIME:LogUtils( 1692): Dictionary info: dictionary = contacts.en_US.dict ; version = ? ; date = ?
D/AndroidRuntime(10785): Shutting down VM
W/dalvikvm(10785): threadid=1: thread exiting with uncaught exception (group=0xacd4eb20)
E/AndroidRuntime(10785): FATAL EXCEPTION: main
E/AndroidRuntime(10785): Process: com.karthikhiraskar.samplesqlitedb, PID: 10785
E/AndroidRuntime(10785): java.lang.NullPointerException
E/AndroidRuntime(10785):    at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:93)
E/AndroidRuntime(10785):    at android.widget.AdapterView.checkFocus(AdapterView.java:713)
E/AndroidRuntime(10785):    at android.widget.AdapterView$AdapterDataSetObserver.onInvalidated(AdapterView.java:836)
E/AndroidRuntime(10785):    at android.widget.AbsListView$AdapterDataSetObserver.onInvalidated(AbsListView.java:6288)
E/AndroidRuntime(10785):    at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:50)
E/AndroidRuntime(10785):    at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:59)
E/AndroidRuntime(10785):    at android.widget.SimpleAdapter$SimpleFilter.publishResults(SimpleAdapter.java:383)
E/AndroidRuntime(10785):    at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
E/AndroidRuntime(10785):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(10785):    at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime(10785):    at android.app.ActivityThread.main(ActivityThread.java:5017)
E/AndroidRuntime(10785):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(10785):    at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime(10785):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
E/AndroidRuntime(10785):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
E/AndroidRuntime(10785):    at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager( 1596):   Force finishing activity com.karthikhiraskar.samplesqlitedb/.MyCustomListView
D/dalvikvm( 1596): GC_FOR_ALLOC freed 505K, 21% free 9295K/11692K, paused 7ms, total 7ms
W/ActivityManager( 1596): Activity pause timeout for ActivityRecordad45ab60 u0 com.karthikhiraskar.samplesqlitedb/.MyCustomListView t59 f
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/Audioservice( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressStandard.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressStandard.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressSpacebar.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressSpacebar.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressDelete.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressDelete.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressReturn.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressReturn.ogg
I/Process (10785): Sending signal. PID: 10785 SIG: 9
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressInvalid.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressInvalid.ogg
W/AudioService( 1596): onLoadSoundEffects(), Error -1 while loading samples
W/InputDispatcher( 1596): channel 'ad54e4b0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
E/InputDispatcher( 1596): channel 'ad54e4b0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView (server)' ~ Channel is unrecoverably broken and will be disposed!
I/ActivityManager( 1596): Process com.karthikhiraskar.samplesqlitedb (pid 10785) has died.
W/InputDispatcher( 1596): Attempted to unregister already unregistered input channel 'ad54e4b0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView (server)'
W/Binder  ( 1692): Caught a RuntimeException from the binder stub implementation.
W/Binder  ( 1692): java.lang.NullPointerException
W/Binder  ( 1692):  at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
W/Binder  ( 1692):  at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
W/Binder  ( 1692):  at android.os.Binder.execTransact(Binder.java:404)
W/Binder  ( 1692):  at dalvik.system.NativeStart.run(Native Method)
W/SurfaceFlinger( 1162): couldn't log to binary event log: overflow.
I/WindowState( 1596): WIN DEATH: Windowad54e4b0 u0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView
W/InputMethodManagerService( 1596): Got RemoteException sending setActive(false) notification to pid 10785 uid 10060
W/PlatformStatsUtil( 2013): Could not retrieve Usage & Diagnostics setting. Giving up.

【问题讨论】:

您阅读过崩溃报告吗?在此处添加崩溃日志。 @KarthikKumarHiraskar- 请粘贴您的适配器和崩溃报告。您可以在此处复制粘贴您的 logcat 报告。 @KarthikKumarHiraskar- 请在此处添加您的适配器,因为我想看到您的过滤方法,并且由于您的适配器没有获得任何列表而发生 NullPointerException。所以也请添加您的适配器。 @RahulGupta,我正在使用标准的 SimpleAdaptor,我将在下面尝试您的解决方案并让您知道它是否有效.. 感谢您的回答建议。 & 不知道为什么有人对这个问题投了反对票.. 【参考方案1】:

如果您搜索任何东西,您将使用 Textchange 侦听器,我们将使用两个数据列表,一个用于备份,另一个用于根据搜索重新填充。

 edit_text.addTextChangedListener(new TextWatcher() 

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) 
            List<LocationSearchModel> textToCheckList=new ArrayList<>();
            String textToCheck=s.toString();
            if(s.length()!=0)
                //code for making First letter of string CAPITAL
                textToCheck = textToCheck.substring(0, 1).toUpperCase() + textToCheck.substring(1); 

                //code for filling second list from backup list based on text to search here in this case, it is "textToCheck"
                for (LocationSearchModel searchModel: locationSearchList) 
                    if(searchModel.getLocationName().startsWith(textToCheck))
                        textToCheckList.add(searchModel);
                    
                
            else
                textToCheckList.addAll(locationSearchList) ;
            

            // Setting new list to adapter and notifying it
            locationSearchAdapter.setLocationSearchList(textToCheckList);
            locationSearchAdapter.notifyDataSetChanged();
        

    );

在上述情况下,“locationSearchList”是我的备份列表,我将使用它来填充我的第二个列表,即

 List<LocationSearchModel> textToCheckList=new ArrayList<>();

在这种情况下。

我已经在上面的代码中提到了 cmets,按照它,你会找到解决方案。如果发现确实如此,请标记我的解决方案使用已满。

【讨论】:

以上是关于Android - 将搜索栏添加到自定义列表视图和简单适配器的主要内容,如果未能解决你的问题,请参考以下文章

如何将搜索添加到列表视图android,按您的类型对项目进行排序

android - 搜索列表视图?

列表视图滚动时隐藏搜索栏

如何正确连接并显示从 Firebase 到自定义列表视图 Android Studio 的数据

如何添加到自定义列表视图用户控制编辑项目列组等任务?

将多个自定义栏按钮添加到自定义导航栏