如何搜索搜索字符串中的任何字符?

时间:2015-09-18 15:25:10

标签: android regex android-layout android-fragments

我目前正在使用字符序列来搜索我的字符串。如何搜索字符串中的任何字符?例如:我有名字"贾斯汀"和#34;杰克",如果我把" K"只有杰克出现,当我把s"贾斯汀和杰克都出现了,因为他们有字母s,如果我把我们只是贾斯汀出现等等。我该怎么办呢? 到目前为止,这是我的代码:

inputSearch.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                // When user changed the Text

                MainActivity.this.adapter.getFilter().filter(cs);
            }

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

            }

这是我用于测试项目的完整示例示例代码: http://www.androidhive.info/2012/09/android-adding-search-functionality-to-listview/

7 个答案:

答案 0 :(得分:3)

在适配器中尝试以下代码以获取列表中的过滤器数据:

        private Filter mFilter;
        private List<String> mCompleteList,mList;

        @Override
        public Filter getFilter() {
        if (mFilter == null) {
        mFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();

                if (constraint == null || constraint.length() == 0) {
                    results.values = mCompleteList;
                    results.count = mCompleteList.size();
                } else {
                    List<String> beanList = new ArrayList<String>();

                    for (String bean : mCompleteList) {
                        if (bean.toUpperCase().contains(constraint.toString().toUpperCase())) {
                            beanList.add(bean);
                        }
                    }
                    results.values = beanList;
                    results.count = beanList.size();
                }
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                mList = (List<String>) results.values;
                notifyDataSetChanged();
            }
        };
    }
    return mFilter;
}

并且不需要MainActivity.this.adapter.getFilter()。filter(cs);在文本更改中,您只需使用adapter.getFilter()。filter(cs);因为适配器是类的私有变量。

答案 1 :(得分:1)

让我们为您的案例编写一些示例代码。

#right {

 max-height:250px;   //edit your own height
 overflow:scroll;
   }

答案 2 :(得分:0)

之后

lv = (ListView) findViewById(R.id.list_view);

如下所述添加此行,

lv.setTextFilterEnabled(true);

因此,您将获得类似于this示例的结果。

答案 3 :(得分:0)

试试这个,

main.xml中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical"
    android:focusable="true"
    android:focusableInTouchMode="true">

    <EditText
        android:id="@+id/editTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:maxLines="1" />

    <ListView android:id="@+id/listView" 
              android:layout_height="match_parent"
              android:layout_width="match_parent"
              android:layout_weight="1"/>


    <Button android:id="@+id/addBtn"
            android:text="Add planet"
            android:onClick="addPlanet"
            android:layout_weight="0.5"
            android:layout_height="80dp"
            android:layout_width="match_parent"/>


</LinearLayout>

这是你的dialog.xml

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

    <EditText
        android:id="@+id/editTextPlanet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="Insert your planet name" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Add" />

</LinearLayout>

这是你的img_row_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        android:paddingLeft="0dip"
        android:src="@drawable/planet" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/img"
        android:layout_toRightOf="@+id/img"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/dist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/name"
        android:layout_gravity="center"
        android:layout_marginTop="2dip"
        android:layout_toRightOf="@id/img"
        android:gravity="right"
        android:textSize="8dp"
        android:textStyle="italic" />

</RelativeLayout>

这是你的row_layout.xml

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

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" 
        android:textStyle="bold"
        />

    <TextView
        android:id="@+id/dist"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="8dp"
        android:textStyle="italic"/>

</LinearLayout>

这是你的Planet.java

/*
 * Copyright (C) 2012 jfrankie (http://www.survivingwithandroid.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.survivingwithandroid.listview.SimpleList;

public class Planet {

    private String name;
    private Integer distance;
    private String descr;
    private int idImg;



    public Planet(String name, Integer distance) {
        this.name = name;
        this.distance = distance;
    }

    public Planet(String name, String descr) {
        this.name = name;
        this.descr = descr;
    }

    public Planet(String name, Integer distance, String descr, int idImg) {
        this.name = name;
        this.distance = distance;
        this.descr = descr;
        this.idImg = idImg;
    }


    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getDistance() {
        return distance;
    }
    public void setDistance(Integer distance) {
        this.distance = distance;
    }
    public int getIdImg() {
        return idImg;
    }
    public void setIdImg(int idImg) {
        this.idImg = idImg;
    }


}

这是你的PlanetAdapter.java

/*
 * Copyright (C) 2012 jfrankie (http://www.survivingwithandroid.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.survivingwithandroid.listview.SimpleList;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

public class PlanetAdapter extends ArrayAdapter<Planet> implements Filterable {

    private List<Planet> planetList;
    private Context context;
    private Filter planetFilter;
    private List<Planet> origPlanetList;

    public PlanetAdapter(List<Planet> planetList, Context ctx) {
        super(ctx, R.layout.img_row_layout, planetList);
        this.planetList = planetList;
        this.context = ctx;
        this.origPlanetList = planetList;
    }

    public int getCount() {
        return planetList.size();
    }

    public Planet getItem(int position) {
        return planetList.get(position);
    }

    public long getItemId(int position) {
        return planetList.get(position).hashCode();
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;

        PlanetHolder holder = new PlanetHolder();

        // First let's verify the convertView is not null
        if (convertView == null) {
            // This a new view we inflate the new layout
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.img_row_layout, null);
            // Now we can fill the layout with the right values
            TextView tv = (TextView) v.findViewById(R.id.name);
            TextView distView = (TextView) v.findViewById(R.id.dist);


            holder.planetNameView = tv;
            holder.distView = distView;

            v.setTag(holder);
        }
        else 
            holder = (PlanetHolder) v.getTag();

        Planet p = planetList.get(position);
        holder.planetNameView.setText(p.getName());
        holder.distView.setText("" + p.getDistance());


        return v;
    }

    public void resetData() {
        planetList = origPlanetList;
    }


    /* *********************************
     * We use the holder pattern        
     * It makes the view faster and avoid finding the component
     * **********************************/

    private static class PlanetHolder {
        public TextView planetNameView;
        public TextView distView;
    }



    /*
     * We create our filter 
     */

    @Override
    public Filter getFilter() {
        if (planetFilter == null)
            planetFilter = new PlanetFilter();

        return planetFilter;
    }



    private class PlanetFilter extends Filter {



        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            // We implement here the filter logic
            if (constraint == null || constraint.length() == 0) {
                // No filter implemented we return all the list
                results.values = origPlanetList;
                results.count = origPlanetList.size();
            }
            else {
                // We perform filtering operation
                List<Planet> nPlanetList = new ArrayList<Planet>();

                for (Planet p : planetList) {
                    if (p.getName().toUpperCase().startsWith(constraint.toString().toUpperCase()))
                        nPlanetList.add(p);
                }

                results.values = nPlanetList;
                results.count = nPlanetList.size();

            }
            return results;
        }

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

            // Now we have to inform the adapter about the new list filtered
            if (results.count == 0)
                notifyDataSetInvalidated();
            else {
                planetList = (List<Planet>) results.values;
                notifyDataSetChanged();
            }

        }

    }
}

这是你的MainActivity.java

/*
 * Copyright (C) 2012 jfrankie (http://www.survivingwithandroid.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.survivingwithandroid.listview.SimpleList;

/**
 * @author Surviving with android (jfrankie)
 *
 */
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.os.Bundle;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    // The data to show
    List<Planet> planetsList = new ArrayList<Planet>();
    PlanetAdapter aAdpt;

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

        initList();

        // We get the ListView component from the layout
        ListView lv = (ListView) findViewById(R.id.listView);


        // This is a simple adapter that accepts as parameter
        // Context
        // Data list
        // The row layout that is used during the row creation
        // The keys used to retrieve the data
        // The View id used to show the data. The key number and the view id must match
        //aAdpt = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, planetsList);
        aAdpt = new PlanetAdapter(planetsList, this);
        lv.setAdapter(aAdpt);

        // React to user clicks on item
//        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//
//          public void onItemClick(AdapterView<?> parentAdapter, View view, int position,
//                  long id) {
//              
//              
//              // We know the View is a <extView so we can cast it
//              TextView clickedView = (TextView) view;
//
//              Toast.makeText(MainActivity.this, "Item with id ["+id+"] - Position ["+position+"] - Planet ["+clickedView.getText()+"]", Toast.LENGTH_SHORT).show();
//
//          }
//         });

          // we register for the contextmneu        
          registerForContextMenu(lv);

          // TextFilter
          lv.setTextFilterEnabled(true);
          EditText editTxt = (EditText) findViewById(R.id.editTxt);          

          editTxt.addTextChangedListener(new TextWatcher() {

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    System.out.println("Text ["+s+"] - Start ["+start+"] - Before ["+before+"] - Count ["+count+"]");
                    if (count < before) {
                        // We're deleting char so we need to reset the adapter data
                        aAdpt.resetData();
                    }

                    aAdpt.getFilter().filter(s.toString());

                }

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

                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            });
        }


     // We want to create a context Menu when the user long click on an item
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {

        super.onCreateContextMenu(menu, v, menuInfo);
        AdapterContextMenuInfo aInfo = (AdapterContextMenuInfo) menuInfo;

        // We know that each row in the adapter is a Map
        Planet planet =  aAdpt.getItem(aInfo.position);

        menu.setHeaderTitle("Options for " + planet.getName());
        menu.add(1, 1, 1, "Details");
        menu.add(1, 2, 2, "Delete");

    }




    // This method is called when user selects an Item in the Context menu
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        AdapterContextMenuInfo aInfo = (AdapterContextMenuInfo) item.getMenuInfo();
        planetsList.remove(aInfo.position);
        aAdpt.notifyDataSetChanged();
        return true;
    }


    private void initList() {
        // We populate the planets

        planetsList.add(new Planet("Mercury", 10));
        planetsList.add(new Planet("Venus", 20));
        planetsList.add(new Planet("Mars", 30));
        planetsList.add(new Planet("Jupiter", 40));
        planetsList.add(new Planet("Saturn", 50));
        planetsList.add(new Planet("Uranus", 60));
        planetsList.add(new Planet("Neptune", 70));


    }


    // Handle user click
    public void addPlanet(View view) {
        final Dialog d = new Dialog(this);
        d.setContentView(R.layout.dialog);
        d.setTitle("Add planet");
        d.setCancelable(true);

        final EditText edit = (EditText) d.findViewById(R.id.editTextPlanet);
        Button b = (Button) d.findViewById(R.id.button1);
        b.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                String planetName = edit.getText().toString();
                MainActivity.this.planetsList.add(new Planet(planetName, 0));
                MainActivity.this.aAdpt.notifyDataSetChanged(); // We notify the data model is changed
                d.dismiss();
            }
        });

        d.show();
    }


}

就是这样。

答案 4 :(得分:0)

请找到工作样本,

inputSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text

            MainActivity.this.adapter.filter(cs);
        }

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

        }

在适配器中创建自己的过滤方法

 public class FieldsAdapter extends BaseAdapter{
    Context mContext;
    LayoutInflater inflater;
    private List<String> mainDataList = null;
    private ArrayList<String> arrayList;
    public FieldsAdapter(Context context,List<String> fieldList) {
        mContext = context;
        mainDataList = fieldList;
        inflater = LayoutInflater.from(context);
        this.arrayList = new ArrayList<String>();
        this.arrayList.addAll(mainDataList);
    }

    @Override
    public int getCount() {
        return mainDataList.size();
    }

    @Override
    public Object getItem(int position) {
        return mainDataList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if(convertView == null){
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.edit_field_item, null);
            holder.txtFieldName = (TextView) convertView.findViewById(R.id.txt_field_name);         
            convertView.setTag(holder);

        }else{
            holder = (ViewHolder) convertView.getTag();
        }       
        holder.txtFieldName.setText(mainDataList.get(position));        
        return convertView;
    }

    static class ViewHolder{
        protected TextView txtFieldName;            
    }   

    public void filter(String queryText){
        queryText = queryText.toLowerCase();
        mainDataList.clear();
        if(queryText.length()==0){
            mainDataList.addAll(arrayList);
        }else{
            for(FieldsPOJO field:arrayList){
                if(field.getFieldName().toString().toLowerCase().contains(queryText)){
                    mainDataList.add(field);
                }
            }
        }
        notifyDataSetChanged();
    }       
}

如果您有任何疑问,请随时在评论部分发布您的疑问。快乐的编码..

答案 5 :(得分:0)

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<UserCommunicationStatus> filteredItems = new ArrayList<UserCommunicationStatus>();

            for (int i = 0, l = AllcommuserList.size(); i < l; i++) {
                UserCommunicationStatus m = AllcommuserList.get(i);
                String name = m.getFirstName().toLowerCase() + " " + m.getLastName().toLowerCase();
                if (name.contains(constraint))
                    filteredItems.add(m);
            }
            result.count = filteredItems.size();
            result.values = filteredItems;
        } else {
            synchronized (this) {
                result.values = AllcommuserList;
                result.count = AllcommuserList.size();
            }
        }
        return result;
    }

这是我的实施,我得到的结果与你提出的相同,我希望这会有所帮助。

由于

答案 6 :(得分:0)

实际上,Android中的默认Arrayadapter类似乎只从整个单词的开头开始搜索,但是通过使用自定义Arrayadapter类,您可以搜索任意字符串的一部分。 我创建了整个自定义类并发布了库。 这是非常容易使用。 您可以从here或单击下面提供的链接来检查实施和使用情况。

https://github.com/mohitjha727/Advanced-Search-Filter


您可以参考这个简单的例子-

我们有“ Mohit”和“ Rohan”这两个名字,如果仅输入“ M”,则Mohit出现在搜索结果中,但是当我们输入“ oh”时,Mohit和Rohan都会出现,因为它们具有共同的字母“哦'。

谢谢。