Android 一般项目的 搜索功能 历史记录排序实现

来源:互联网 发布:罗德曼生涯数据 编辑:程序博客网 时间:2024/06/05 08:14

先看张效果图,


素材有点low,软键盘右下角回车变成搜索按钮。这种实现只需要在edittext上加入Android:imeOptions="actionSearch"即可,这个也根据版本的2.3以上就必须添加android:singleLine="true",这个可以理解,因为单行为true时,回车就不会起作用。

先看下整体的布局 

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:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayout    android:layout_width="match_parent"    android:layout_height="45dp"    android:background="#14141F"    android:gravity="center_vertical"    android:orientation="horizontal"    android:paddingBottom="6dp"    android:paddingTop="6dp">    <ImageView        android:id="@+id/iv_back"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:paddingLeft="14dp"        android:paddingRight="14dp"        android:src="@mipmap/icon"/>    <RelativeLayout        android:id="@+id/rl_search_layout"        android:layout_width="0dp"        android:layout_weight="1"        android:layout_height="wrap_content"        android:gravity="center"        android:orientation="horizontal">        <EditText            android:id="@+id/et_search"            android:layout_width="match_parent"            android:layout_height="30dp"            android:layout_centerVertical="true"            android:layout_marginLeft="10dp"            android:background="@null"            android:hint="输入商品名或者店铺名称"            android:imeOptions="actionSearch"        android:singleLine="true"            android:textColor="#FFFFFF"            android:textColorHint="#7F7F7F"            android:textSize="14sp" />    </RelativeLayout>    <TextView        android:id="@+id/tv_cancel"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="14dp"        android:layout_marginRight="14dp"        android:gravity="center_vertical"        android:text="取消"        android:textColor="#FFFFFF"        android:textSize="18sp" /></LinearLayout><LinearLayout    android:id="@+id/ll_search_history"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginBottom="14dp"        android:layout_marginLeft="14dp"        android:layout_marginTop="14dp"        android:drawableLeft="@mipmap/brand_search_history_icon"        android:drawablePadding="10dp"        android:text="历史记录"        android:textColor="#333333" />    <View        android:layout_width="match_parent"        android:layout_height="1dp"        android:background="#dfdfdf" />    <ListView        android:id="@+id/listView"        android:divider="@null"        android:layout_width="match_parent"        android:layout_height="wrap_content">    </ListView> </LinearLayout></LinearLayout>

布局大体就为这样,整个流程就是当用户在输入框输入内容时,点击软键盘的搜索按钮,会做出一定的逻辑处理,Demo就Toast一句话而已。保存搜索内容作为搜索历史记录,在保存的时候采用的sp(SharedPreferences)来实现。

需要注意的是 setOnEditorActionListener这个方法,并不是在我们点击EditText的时候触发,也不是在我们对EditText进行编辑时触发,而是在我们编辑完之后点击软键盘上的回车键才会触发。我们把回车键改为搜索键,所以当我们点击搜索时,监听方法会触发,实现搜索的具体逻辑。


//监听软键盘输入法按下【搜索】事件。    etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {        @Override        public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {            if (actionId == EditorInfo.IME_ACTION_SEARCH) {                // 先隐藏键盘                ((InputMethodManager) etSearch.getContext().getSystemService(Context.INPUT_METHOD_SERVICE))                        .hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);                //搜索具体逻辑                Toast.makeText(getApplicationContext(),"已经跳转到"+etSearch.getText()+"界面",Toast.LENGTH_SHORT).show();                //保存历史记录                saveSearchHistory(String.valueOf(etSearch.getText()));                return true;            }            return false;        }    });

接下来看下是如何保存的呢,采用键值对的方式,key为搜索时候的时间戳,value则为搜索时候的关键字,采用时间戳的做法相对于后期实现历史记录动态改变实现比较方便,按时间戳排序即可。所谓的动态改变就是原本为第二个的历史记录,我们再次搜索,会更改为最新的。但保存的时候要先做一步判断,查询一些是否存在,存在我们则删除,然后在put添加。下面代码就是采用遍历Map的效率高的一种方法entrySet(),entrySet是 键-值 对的集合,Set里面的类型是Map.Entry,

举个例子我们来看下entrySet()方法两种遍历:

public static void main(String[] args) {     Map<String,String> map=new HashMap<String,String>();    map.put("1", "小王");    map.put("2", "小陈");    map.put("3", "小李");    /*方法一 :迭代程序*/        System.out.println("方法一:");        Iterator iterator=map.entrySet().iterator();        while(iterator.hasNext()){           Map.Entry<String, String> entry= (Entry<String, String>) iterator.next();            System.out.println("key:"+entry.getKey()+" value"+entry.getValue());           }            /*方法二*/        System.out.println("方法二:");        for (Map.Entry<String, String> m : map.entrySet()) {           System.out.println("key:"+m.getKey()+" value"+m.getValue());         }     }

 private void saveSearchHistory(String keyWords) {    //保存之前要先查询sp中是否有该value的记录,有则删除.这样保证搜索历史记录不会有重复条目    Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());    for (Map.Entry<String, String> entry : historys.entrySet()) {        if(keyWords.equals(entry.getValue())){            SearchHistoryUtils.remove(getApplicationContext(),entry.getKey());        }    }    SearchHistoryUtils.put(getApplicationContext(), "" + mFormat.format(new Date()), keyWords);}

历史记录保存我们实现了,那么接下来就是展示的了,根据搜索的时间先后排序来展示的,当不存在历史记录时,隐藏footView,也就是清空历史记录那块布局。

private void showSearchHistory() {    Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());    //将key排序升序    Object[] keys = hisAll.keySet().toArray();    Arrays.sort(keys);    int keyLeng = keys.length;    //这里计算 如果历史记录条数是大于 可以显示的最大条数,则用最大条数做循环条件,防止历史记录条数-最大条数为负值,数组越界    int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng;    for (int i = 1; i <= hisLeng; i++) {        mResults.add(hisAll.get(keys[keyLeng - i]));    }    mListView.setAdapter(mAdapter);    //如果size不为0 显示footerview    mFooterView.setVisibility(0!=mResults.size()? View.VISIBLE:View.GONE);}

整个Activity

public class MainActivity extends AppCompatActivity {private EditText etSearch;private static final int MSG_SEARCH = 1;private static final int HISTORY_MAX = 5;//最多显示五条历史记录private Context mContext;private SimpleDateFormat mFormat;private ListView mListView;private View mFooterView;private MyAdapter mAdapter;private TextView tvCancel;List<String> mResults = new ArrayList<String>();protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    initView();    initListener();    showSearchHistory();}private void initView() {    etSearch=(EditText)findViewById(R.id.et_search);    tvCancel= ((TextView) findViewById(R.id.tv_cancel));    mFormat = new SimpleDateFormat("yyyyMMddHHmmss");    mListView=(ListView)findViewById(R.id.listView);    LayoutInflater layoutInflater =            (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);    mFooterView = layoutInflater.inflate(R.layout.footview, null);    mListView.addFooterView(mFooterView);    mAdapter=new MyAdapter(this);}private void initListener() {    //监听软键盘输入法按下【搜索】事件。    etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {        @Override        public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {            if (actionId == EditorInfo.IME_ACTION_SEARCH) {                // 先隐藏键盘                ((InputMethodManager) etSearch.getContext().getSystemService(Context.INPUT_METHOD_SERVICE))                        .hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);                //搜索具体逻辑                Toast.makeText(getApplicationContext(),"已经跳转到"+etSearch.getText()+"界面",Toast.LENGTH_SHORT).show();                //搜索请求转交给函数去处理                saveSearchHistory(String.valueOf(etSearch.getText()));                return true;            }            return false;        }    });    // 清空历史记录点击事件    mFooterView.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View view) {            clearsearchHistory();        }    });    //取消按钮点击事件    tvCancel.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View view) {           etSearch.setText("");        }    });}/** */private void saveSearchHistory(String keyWords) {    //保存之前要先查询sp中是否有该value的记录,有则删除.这样保证搜索历史记录不会有重复条目    Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());    for (Map.Entry<String, String> entry : historys.entrySet()) {        if(keyWords.equals(entry.getValue())){            SearchHistoryUtils.remove(getApplicationContext(),entry.getKey());        }    }    SearchHistoryUtils.put(getApplicationContext(), "" + mFormat.format(new Date()), keyWords);}private void showSearchHistory() {    Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());    //将key排序升序    Object[] keys = hisAll.keySet().toArray();    Arrays.sort(keys);    int keyLeng = keys.length;    //这里计算 如果历史记录条数是大于 可以显示的最大条数,则用最大条数做循环条件,防止历史记录条数-最大条数为负值,数组越界    int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng;    for (int i = 1; i <= hisLeng; i++) {        mResults.add(hisAll.get(keys[keyLeng - i]));    }    mListView.setAdapter(mAdapter);    //如果size不为0 显示footerview    mFooterView.setVisibility(0!=mResults.size()? View.VISIBLE:View.GONE);}private void clearsearchHistory() {    SearchHistoryUtils.clear(this);    //同时刷新历史记录显示页面    mResults = new ArrayList<>();    mListView.setAdapter(mAdapter);    //mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,mResults));    //如果size不为0 显示footerview    mFooterView.setVisibility(0!=mResults.size()?View.VISIBLE:View.GONE);}public class  MyAdapter extends BaseAdapter {    private LayoutInflater mInflater = null;    private MyAdapter(Context context)    {        //根据context上下文加载布局,这里的是Demo17Activity本身,即this        this.mInflater = LayoutInflater.from(context);    }    public int getCount() {        return mResults.size();    }    @Override    public Object getItem(int i) {        return mResults.get(i);    }    @Override    public long getItemId(int i) {        return i;    }    @Override    public View getView(int i, View convertView, ViewGroup viewGroup) {        ViewHolder holder;        if(convertView == null)        {            holder = new ViewHolder();            convertView = mInflater.inflate(R.layout.lvitem, null);            holder.title= ((TextView) convertView.findViewById(R.id.info));            convertView.setTag(holder);        }else        {            holder = (ViewHolder)convertView.getTag();        }        holder.title.setText(mResults.get(i));        return convertView;    }}    static class ViewHolder    {        public TextView title;    }}

就是一个listView展示历史记录,其中有一个item布局,和一个footView布局

footview.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="match_parent"android:layout_height="match_parent"><ImageView    android:id="@+id/ivClearAll"    android:layout_width="15dp"    android:layout_height="15dp"    android:src="@mipmap/clear"    android:layout_alignParentTop="true"    android:layout_alignParentStart="true"    android:layout_marginStart="177dp"    android:layout_marginTop="16dp" /><TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="清空历史记录"    android:textSize="15sp"    android:layout_alignTop="@+id/ivClearAll"    android:layout_toEndOf="@+id/ivClearAll" /></RelativeLayout>

lvitem.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayout    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal"    >    <TextView        android:id="@+id/info"        android:layout_marginTop="12dp"        android:layout_marginLeft="35dp"        android:layout_width="wrap_content"        android:text="电子商务"        android:textColor="#333333"        android:layout_height="40dp" /></LinearLayout><View    android:layout_width="match_parent"    android:layout_height="1dp"    android:background="#dfdfdf" /></LinearLayout>
工具类传送门  http://download.csdn.net/detail/u012896330/9728714
2 0
原创粉丝点击