Android歷史搜索

又是一輪新需求,實現本地搜索,估計其實很多地方都有用到過,尤其電商類APP。作爲自己親歷實現的又一功能,自己做一個小的標註。


閒話少敘,直入主題~_~ ~_~ ~_~ ~_~

需求:

1,實現搜索功能,將搜索關鍵詞保存並展示;

2,搜索關鍵詞輸入內容無限制;

3,APP關閉重啓後,歷史搜索可展示;

4,歷史搜索關鍵詞重複則將其提至最開始;【去重複,佔首位】


技術實現:

1,本地文件保存,使用SP,將關鍵詞串成字符串保存;

2,分割符使用空格,在內容輸入空格時,保存關鍵詞時將空格過濾。


編碼過程:

1,xml實現佈局;

2,類承接獲取View;

3,初始化數據,並刷新頁面;

4,交互操作,保存更新數據,刷新頁面;

5,異常情形考慮,細節維護。


佈局文件:

<?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:background="@color/page_bg_color"
    android:orientation="vertical">
    <!--搜索頁面佈局文件-->
    <!-- ***************************** title ********************************* -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="13dp"
            android:layout_weight="1"
            android:background="@mipmap/search_title_bg_pic"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="12dp"
                android:src="@mipmap/search_inner_pic" />

            <EditText
                android:id="@+id/search_key_words_et"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_weight="1"
                android:background="@null"
                android:hint="字體名"
                android:imeOptions="actionSearch"
                android:maxLines="1"
                android:padding="10dp"
                android:textSize="16sp" />

            <ImageView
                android:id="@+id/clear_content_iv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="12dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/del_search_content_pic"
                android:visibility="invisible" />

        </LinearLayout>

        <TextView
            android:id="@+id/search_cancel_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="10dp"
            android:clickable="true"
            android:text="取消"
            android:textSize="16sp" />

    </LinearLayout>
    <!-- ***************************** title ********************************* -->

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="搜索歷史"
            android:textSize="15sp" />

        <ImageView
            android:id="@+id/clear_history_iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="10dp"
            android:src="@mipmap/del_history_pic"
            android:visibility="gone" />
    </RelativeLayout>


    <ListView
        android:id="@+id/search_history_lv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:headerDividersEnabled="true"
        android:scrollbars="none" />


</LinearLayout>

代碼實現:

public class MainActivity extends Activity implements View.OnClickListener {

    //=========常量================================================================
    /**
     * 搜索歷史關鍵字
     */
    private static final String SEARCH_HISTORY_KEY = "seach_history_key";


    //==========View================================================================
    /**
     * 搜索關鍵字輸入
     */
    private EditText searchKeyWordsET;
    /**
     * 標題欄 - 取消
     */
    private TextView topCancelTV;
    /**
     * 清除歷史搜索
     */
    private ImageView clearHistoryIV;
    /**
     * 搜索歷史展示
     */
    private ListView searchHistoryLV;
    /**
     * 清除輸入內容
     */
    private ImageView clearContentIV;

    //=========數據================================================================
    /**
     * 搜索歷史具體內容
     */
    private List<String> searchHistoryList;
    /**
     * 搜索歷史適配器
     */
    private ArrayAdapter<String> adapter;
    /**
     * 已經開啓了新的Activity
     */
    private boolean startedActivity = false;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_search);
        initView();
        initListener();
        initData();
        refreshPageView();
        showSoftInputFromWindow(MainActivity.this, searchKeyWordsET);

    }


    /**
     * 初始化頁面控件
     */
    private void initView() {
        searchKeyWordsET = (EditText) findViewById(R.id.search_key_words_et);
        topCancelTV = (TextView) findViewById(R.id.search_cancel_tv);
        clearHistoryIV = (ImageView) findViewById(R.id.clear_history_iv);
        searchHistoryLV = (ListView) findViewById(R.id.search_history_lv);
        clearContentIV = (ImageView) findViewById(R.id.clear_content_iv);

        searchHistoryLV.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    }

    /**
     * 初始化監聽器
     */
    private void initListener() {
        topCancelTV.setOnClickListener(this);
        clearHistoryIV.setOnClickListener(this);
        clearContentIV.setOnClickListener(this);
        searchKeyWordsET.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEND || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
                    /**
                     * 點擊“搜索”後的處理
                     */
                    String keyWord = searchKeyWordsET.getText().toString().trim();
                    keyWord = keyWord.replace(" ", "");

                    if (!TextUtils.isEmpty(keyWord)) {//爲空不處理
                        searchHistoryLV.setVisibility(View.VISIBLE);
                        clearHistoryIV.setVisibility(View.VISIBLE);
                        //去重複、保存內容、長度確認
                        /**
                         * 保存長串中出現短串  會出現異常
                         * 只能在數組中判斷
                         */
                       /*
                        String historyContent = SharedPreferencesUtil.getString(ActivitySearch.this, SEARCH_HISTORY_KEY, "");
                        if (historyContent.length() > 0) {
                            if (historyContent.contains(keyWord)) {//有重複
                                String historySubContent = getSubString(historyContent, keyWord + " ");
                                SharedPreferencesUtil.putString(ActivitySearch.this, SEARCH_HISTORY_KEY, keyWord + " " + historySubContent);
                            } else {
                                SharedPreferencesUtil.putString(ActivitySearch.this, SEARCH_HISTORY_KEY, keyWord + " " + historyContent);
                            }
                        } else {//沒有保存過內容
                            SharedPreferencesUtil.putString(ActivitySearch.this, SEARCH_HISTORY_KEY, keyWord + " ");
                        }
                        */
                        if (searchHistoryList == null) {
                            initData();
                        }
                        //去重複
                        Iterator<String> iterator = searchHistoryList.iterator();
                        while (iterator.hasNext()) {
                            String item = iterator.next();
                            if (keyWord.equals(item)) {
                                iterator.remove();
                            }
                        }

                        searchHistoryList.add(0, keyWord);
                        //數據量控制
                        if (searchHistoryList.size() > 5) {
                            for (int i = 4; i < searchHistoryList.size(); i++) {
                                searchHistoryList.remove(5);
                            }
                        }
                        if (adapter != null) {
                            adapter.notifyDataSetChanged();
                        } else {
                            refreshPageView();
                        }
                        /**
                         * 當前監聽器會執行兩次
                         */
                        if (!startedActivity) {
                            startedActivity = true;
                            startSearchResultActivity(keyWord);
                        }
                        return true;
                    } else {
                        return false;
                    }
                }
                return false;
            }
        });
        searchHistoryLV.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                final String keyword = searchHistoryList.get(position - 1);
                searchHistoryList.remove(position - 1);
                searchHistoryList.add(0, keyword);
                adapter.notifyDataSetChanged();
                searchKeyWordsET.setText(keyword);
                searchKeyWordsET.setSelection(keyword.length());
                startSearchResultActivity(keyword);
            }
        });

        searchKeyWordsET.addTextChangedListener(new TextWatcher() {
            @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.length() > 0) {
                    clearContentIV.setVisibility(View.VISIBLE);
                } else {
                    clearContentIV.setVisibility(View.INVISIBLE);
                }
            }
        });
    }

    /**
     * 跳轉結果頁面
     *
     * @param keyWord
     */
    private void startSearchResultActivity(String keyWord) {
        if (keyWord == null || "".equalsIgnoreCase(keyWord) || keyWord.length() <= 0) {
            return;
        }
        /**
         * 跳轉結果頁面
         */
//        Intent intent = new Intent(MainActivity.this, ActivitySearchResult.class).putExtra("keyWord", keyWord);
//        startActivity(intent);
    }

    /**
     * 初始化數據
     */
    private void initData() {
        searchHistoryList = new ArrayList<>();
        String historyContent = SharedPreferencesUtil.getString(MainActivity.this, SEARCH_HISTORY_KEY, "");
        if (!"".equalsIgnoreCase(historyContent)) {
            /**
             *  保存有效內容
             *  篩選掉最後保存內容有空格的情形
             *  也可以在保存內容時,最後一個值加判斷條件,過濾掉空格
             */

            String[] historys = historyContent.split(" ");
            if (historys.length > 0) {
                for (int i = 0; i < historys.length; i++) {
                    String history = historys[i].trim();
                    if (history.length() > 0) {
                        searchHistoryList.add(history);
                    }
                }
            }
        }
    }

    /**
     * 刷新頁面
     */
    private void refreshPageView() {
        /**
         * 篩選組合完歷史消息
         */
        if (searchHistoryList != null && searchHistoryList.size() > 0) {
            searchHistoryLV.setVisibility(View.VISIBLE);
            clearHistoryIV.setVisibility(View.VISIBLE);

            adapter = new ArrayAdapter<String>
                    (MainActivity.this, R.layout.item_search_history, searchHistoryList);//item佈局及內容關聯??
            searchHistoryLV.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        } else {
            searchHistoryLV.setVisibility(View.GONE);
            clearHistoryIV.setVisibility(View.GONE);
        }
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            /**
             * 取消
             */
            case R.id.search_cancel_tv:
                finish();//關閉當前頁面
                break;
            /**
             * 清除歷史
             */
            case R.id.clear_history_iv:
                SharedPreferencesUtil.putString(MainActivity.this, SEARCH_HISTORY_KEY, "");
                searchHistoryList.clear();
                adapter.notifyDataSetChanged();
                searchHistoryLV.setVisibility(View.GONE);
                clearHistoryIV.setVisibility(View.GONE);
                break;
            /**
             * 內容輸入清空
             */
            case R.id.clear_content_iv:
                clearContentIV.setVisibility(View.INVISIBLE);
                searchKeyWordsET.setText("");
                break;
        }

    }


    /**
     * EditText獲取焦點並顯示軟鍵盤
     */
    public void showSoftInputFromWindow(Activity activity, EditText editText) {
        editText.setFocusable(true);
        editText.setFocusableInTouchMode(true);
        editText.requestFocus();
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }


    /**
     * 字符串刪除指定子串
     *
     * @param s  是需要刪除某個子串的字符串 【原字符串】
     * @param s1 是需要刪除的子串
     * @return
     */
    public String getSubString(String s, String s1) {
        int postion = s.indexOf(s1);
        int length = s1.length();
        int Length = s.length();
        String newString = s.substring(0, postion) + s.substring(postion + length, Length);
        return newString;//返回已經刪除好的字符串
    }

    @Override
    protected void onStop() {
        super.onStop();
        /**
         * 保存歷史搜索到文件
         */
        if (searchHistoryList != null && searchHistoryList.size() > 0) {
            String result = "";
            for (int i = 0; i < searchHistoryList.size(); i++) {
                result += searchHistoryList.get(i) + " ";
            }
            SharedPreferencesUtil.putString(MainActivity.this, SEARCH_HISTORY_KEY, result);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        startedActivity = false;
    }


    /**
     * 涉及點考慮:
     * 1,內容是需要能夠在應用再次重啓的時候展示的,需要文件化保存,選擇SP,將所有內容保存成爲字符串;
     * 2,分割符:表示所有符號均可以輸入,只能選擇其中特殊的符號,選擇了空格;
     * 3,空格作爲內容輸入時,在保存成爲單個關鍵詞時,篩除所有空格;
     * 4,保存一個關鍵詞,後跟一個空格,在最後一個也有,再從文件讀取時,壓入數組,需要做去空格處理;
     * 5,實際操作中,創建該背時,從文件加載歷史;類存在過程中,一直使用數組;在離開頁面時,再次保存到文件中;
     * 6,另一個思路是所有直接操作文件,使用字符串刪除的指定串的方法;
     *      文件操作中不能直接用於頁面渲染;
     *      存在先有長串關鍵詞,之後有包含關係子串,篩選錯誤,比較多的控制;
     * 7,邏輯方面:
     *      【1】保存內容到文件;
     *      【2】去處重複考慮;
     *      【3】搜索過的內容排序到最前面;
     *      【4】歷史內容保存數量限制;
     *
     * 細節處理:
     *      1,進入頁面,獲取焦點,軟件盤彈出;---- 減少用戶操作,從細節出發;
     *      2,內容輸入,保留清除內容助手 X;
     *      3,EditText監聽器的多次執行,使用變量控制執行次數;【管控目的頁面的啓動模式】
     *
     */

}


實現效果展示:




異次元傳送門:

                                       異次元傳送門





心靈雞湯:偷笑


這一切點滴小事,或許好,或許差,爲的就是讓自己瞭解、認知平凡的自己和平凡的生活。也希望自己能永葆在平凡生活中活出不平凡的動力~_~

發佈了121 篇原創文章 · 獲贊 32 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章