Android 用EditText实现搜索框功能

效果图

效果图


思路

为EditText添加TextChangedListener接口,在接口的afterTextChanged方法里面实现搜索功能


工程目录结构

工程目录结构


1.MainActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

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

public class MainActivity extends Activity {

    private ListView listView;      //列表
    private SearchView searchView;  //搜索框

    private List<String> data = new ArrayList<>();  //ListView数据源

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

        //获取控件
        listView = (ListView) findViewById(R.id.listView);
        searchView = (SearchView) findViewById(R.id.searchView);

//        //设置延时搜索,延时2秒
//        searchView.setWaitTime(2000);

        //设置搜索方法
        searchView.setSearchWay(new SearchView.SearchWay<String>(){

            @Override
            public List<String> getData() {
                //返回数据源
                return data;
            }

            @Override
            public boolean matchItem(String item, String s) {
                //如果串item中包含串s,则匹配
                return item.contains(s);
            }

            @Override
            public void update(List<String> resultList) {
                //更新ListView的数据
                setListViewData(resultList);
            }
        });

        initListView();
    }

    /**
     * 初始化ListView
     */
    private void initListView(){
        //初始化字符数组
        for (int i = 0; i < 20; i++){
            data.add("第" + i + "项");
        }

        //初始化ListView的内容
        setListViewData(data);
    }

    /**
     * 设置ListView的内容
     */
    private void setListViewData(List<String> list){
        //设置ListView的适配器
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list);
        listView.setAdapter(adapter);
    }
}

2.SearchView.java

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;

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

/**
 * Created by Administrator on 2016/8/31.
 * 搜索框
 */
public class SearchView extends LinearLayout implements TextWatcher{

    private EditText et_search;     //输入框
    private ImageView iv_clear;     //删除图标

    private SearchWay mSearch;      //匹配方法
    private String searchText;      //改变后的文字
    private WaitThread waitThread;  //等待线程
    private int waitTime = 200;     //延时搜索时间,默认200ms
    private int curTime;            //当前延时时间
    private Handler mHandler;

    public SearchView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //加载布局文件
        View view = LayoutInflater.from(context).inflate(R.layout.view_search, null);

        //获取控件
        et_search = (EditText) view.findViewById(R.id.et_search);
        iv_clear = (ImageView) view.findViewById(R.id.iv_clear);

        //设置清空按钮的触发器
        iv_clear.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                et_search.setText("");
            }
        });

        //读取属性
        TypedArray typed = context.obtainStyledAttributes(attrs, R.styleable.SearchView);
        String s;
        //文字大小
        float textSize = typed.getDimension(R.styleable.SearchView_sv_textSize, 15);
        et_search.setTextSize(textSize);
        //搜索框文字
        s = typed.getString(R.styleable.SearchView_sv_text);
        if (s != null){
            et_search.setText(s);
        }
        //提示文字
        s = typed.getString(R.styleable.SearchView_sv_hint);
        if (s != null){
            et_search.setHint(s);
        }
        //是否隐藏搜索图标
        boolean hideImg = typed.getBoolean(R.styleable.SearchView_sv_hideImg, false);
        if (hideImg) {
            view.findViewById(R.id.img_search).setVisibility(GONE);
        }
        //回收资源
        typed.recycle();

        //文字改变监听
        et_search.addTextChangedListener(this);

        //异步处理
        mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                //更新回调接口
                if (0 == msg.what){
                    waitThread = null;
                    //匹配结果回调
                    List searchList = new ArrayList();
                    List list = mSearch.getData();
                    if (list != null) {
                        for (Object o : list) {
                            if (mSearch.matchItem(o, searchText)) {
                                searchList.add(o);
                            }
                        }
                        mSearch.update(searchList);
                    }
                }
            }
        };

        //把布局添加到当前控件中
        ViewGroup.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        addView(view, params);
    }

    /**
     * 设置匹配数据的方法
     */
    public void setSearchWay(SearchWay search){
        mSearch = search;
    }

    /**
     * 获取搜索框的文字
     */
    public String getText(){
        return et_search.getText().toString();
    }

    public SearchWay getSearchWay() {
        return mSearch;
    }

    @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) {
        //删除图标
        if (s.toString().isEmpty()){
            iv_clear.setVisibility(GONE);
        }else {
            iv_clear.setVisibility(VISIBLE);
        }

        if (mSearch != null) {
            if (null == waitThread) {
                waitThread = new WaitThread();
                waitThread.start();
            } else {
                //搜索框的文字发生变化就重置等待时间
                if (!searchText.equals(s.toString())) {
                    curTime = 0;
                }
            }
        }

        searchText = s.toString();
    }

    /**
     * 设置搜索延时时间
     * @param waitTime 毫秒,精度为100ms
     */
    public void setWaitTime(int waitTime){
        this.waitTime = waitTime;
    }

    /**
     * 延时搜索的线程
     */
    private class WaitThread extends Thread{
        @Override
        public void run() {
            //等待延时
            for (curTime = 0; curTime < waitTime; curTime += 100){
                try {
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }

            mHandler.sendEmptyMessage(0);
        }
    }

    /**
     * 用于匹配项
     */
    public static abstract class SearchWay<T>{
        /**
         * @return 数据源
         */
        public abstract List<T> getData();

        /**
         * @return item中是否包含有s
         */
        public abstract boolean matchItem(T item, String s);

        /**
         * 更新列表
         * @param resultList 匹配的数据,重新加载到列表
         */
        public abstract void update(List<T> resultList);
    }
}

3.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.ffpy.demo.MainActivity"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:padding="8dp"
        android:background="@android:color/darker_gray">

        <com.ffpy.demo.SearchView
            android:id="@+id/searchView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"/>

    </LinearLayout>

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

</LinearLayout>

4.view_search.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="35dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:paddingLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_centerInParent="true"
        android:gravity="center_vertical">

        <ImageView
            android:id="@+id/img_search"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@mipmap/search"/>

        <EditText
            android:id="@+id/et_search"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_marginLeft="5dp"
            android:background="@android:color/transparent"
            android:singleLine="true" />

        <ImageView
            android:id="@+id/iv_clear"
            android:clickable="true"
            android:visibility="gone"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginLeft="5dp"
            android:scaleType="fitXY"
            android:src="@mipmap/cleartext" />

    </LinearLayout>

</RelativeLayout>


5.attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 搜索框 -->
    <declare-styleable name="SearchView">
        <!-- 搜索框的文字 -->
        <attr name="sv_text" format="string"/>
        <!-- 提示文字 -->
        <attr name="sv_hint" format="string"/>
        <!-- 字体大小 -->
        <attr name="sv_textSize" format="dimension"/>
        <!-- 是否隐藏搜索图标 -->
        <attr name="sv_hideImg" format="boolean"/>
    </declare-styleable>
</resources>

6. cleartext.png


7.search.png


  • 10
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值