Android 一般項目的 搜索功能 歷史記錄排序實現

先看張效果圖,


素材有點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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章