Android projects similar to Taobao's search function, monitor soft keyboard search events, delay automatic search, and time-ordered search history of the implementation _android

Source: Internet
Author: User
Tags gettext

Recently job-hopping to a new company, accepted the first task is in an Electronic Business module search function as well as the search history of the implementation.

Demand and Taobao and other electrical functions roughly similar to the top of a search box, the following display search history. After entering the keyword to search in the EditText, press the soft keyboard search key/delay XXXXMS to search automatically. The content of the search is then displayed to the user/prompts the user not to search the relevant information.

History is sorted by time, the latest in front, enter previously searched keywords, such as jeans (originally the second), will update the time of the record, next time, look at the arrangement of jeans in the first place. and has the ability to purge history.

To sort out the requirements, the following work is generally required:

Functional section:

One, click EditText, pop-up Soft keyboard input method, the bottom right button for "search" words.

Second, listen to soft keyboard Input Method Press the "Search" event.

Third, in the EditText input content, 1000ms no changes in the automatic search function.

Save the history by chronological order,

Five, Clear history

Click the history entry to populate the EditText and perform the search function automatically.

The UI sketch is as follows:

The realization of ===============ui ==================

Search Header Header:

The whole is a horizontal direction linearlayout, placed ImageView (return arrow), EditText (search box), TextView (cancel).

The layout files are as follows:

<linearlayout android:layout_width= "match_parent" android:layout_height= "45DP" android:background= "@color black_14141f "android:gravity=" center_vertical "android:orientation=" horizontal "android:paddingbottom=" 6DP "Andro id: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= "@drawable/ic On_back "/> <relativelayout android:id=" @+id/rl_search_layout "android:layout_width=" 0DP "Android:lay out_weight= "1" android:layout_height= "wrap_content" android:background= "@drawable/shape_search_bj" Android:gra vity= "center" android:orientation= "Horizontal" > <!--<imageview android:layout_centerve Rtical= "true" android:layout_alignparentleft= "true" android:id= "@+id/tv" android:layou
       T_width= "Wrap_content"     android:layout_height= "Wrap_content" android:layout_margintop= "5DP" Android:layout_marginbott Om= "5DP" android:background= "@drawable/icon_black_search"/>--> <edittext android:id= "@+id /et_search "android:layout_width=" match_parent "android:layout_height=" 30DP "android:layout_centervertic Al= "true" android:layout_marginleft= "10DP" android:layout_toleftof= "@+id/close" Android:layout_torightof
      = "@+id/tv" android:background= "@null" android:hint= "Enter the name of the commodity or store" android:imeoptions= "Actionsearch"
      Android:singleline= "true" android:textcolor= "@color/black3" android:textcolorhint= "@color/gray_aaaaaa"
            Android:textsize= "14sp"/> <!--<imageview android:layout_centervertical= "true" Android:layout_alignparentright= "true" android:id= "@+id/clear_search android:background=" @drawa
 Ble/icon_dialog_close "           Android:layout_width= "Wrap_content" android:layout_height= "Wrap_content" Android:gravit y= "center" android:textcolor= "@color/white" android:textsize= "18SP"/>--> </relativela yout> <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_ver 

 Tical "android:text=" Cancel "android:textcolor=" @color/white "android:textsize=" 18sp "/> </LinearLayout>

If you copy directly from a project, replace the resource file with your own.

==================================

History layout:

TextView (History search Four words) +listview (Search Records) +listview Footerview (Purge history) is implemented with a vertical layout of the LinearLayout package.

(Taobao should be a ListView, historical search words with ListView headerview implementation.) And our company's product design history Search the words below the line length and history of the item split line length is not the same, I directly with TextView do, much the same.

The code is as follows:

<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= "@drawable/brand_ Search_history_icon "
    android:drawablepadding=" 10DP "
    android:text=" History "
    android:textcolor=" # 333333 "/>

  <view
    android:layout_width=" match_parent "
    android:layout_height=" 1DP
    " android:background= "@color/bg_dfdfdf"/>

  <listview
    android:id= "@+id/listview"
    android: Divider= "@null"
    android:layout_width= "match_parent"
    android:layout_height= "Wrap_content" ></ Listview>

</LinearLayout>

Split lines are generally implemented with the view settings background, the province's UI Chettu.

================ function Implementation Part ==================

One, click EditText, pop-up Soft keyboard input method, the bottom right button for "search" words.

You only need to configure the following properties in the XML of the EditText control:

Android:imeoptions= "Actionsearch"

=================================

Second, listen to soft keyboard Input Method Press the "Search" event.

For the EditText control, set the Oneditoractionlistener event to determine that when actionid = = Editorinfo.ime_action_search, the search button is pressed.

The code is as follows, where we hide the soft keyboard and execute the search request.

Medittextsearch.setoneditoractionlistener (New Textview.oneditoractionlistener () {
  @Override
  public Boolean oneditoraction (TextView v, int ActionId, keyevent event) {
    if (ActionId = editorinfo.ime_action_search) {
   //First hides the keyboard (
      Inputmethodmanager) Medittextsearch.getcontext (). Getsystemservice (Context.input_method_service) )
          . Hidesoftinputfromwindow (MainActivity.this.getCurrentFocus (). Getwindowtoken (), Inputmethodmanager.hide_ Not_always);
      Search for specific logic
      //Search requests forwarded to the function to process:
      //search (String.valueof (Medittextsearch.gettext ()));
      Toast.maketext (Mainactivity.this, "Press the Search button", Toast.length_short). Show ();
      return true;
    }
    return false;
  }
});

==================================

Third, in the EditText input content, 1000ms no changes in the automatic search function.

Here is the textchangedlistener of listening to EditText, in aftertextchanged (Editable s) callback method, first to determine whether the current edittext of the string is null/null, if it is empty, do not search, Displays the history, or, if not, the Handler.sendmessagedelayed method delays the 500ms/1000ms to perform the search function.

There's a situation here, if the user entered the new content within 1000ms, the deletion of characters, should be delayed 1000ms search for new content, or delete characters after the empty, it should not be searched, that is, users in 1000ms within the changes should be based on the latest situation as logical judgment. So here before the judge added a statement, every time the Aftertextchanged () method is executed, the first to determine whether there is an Mhandler search request, if so, remove this request message first.

The code is as follows: Here the handler is introduced, mainly for the purpose of delaying automatic searching and for canceling the search request.

 Medittextsearch.addtextchangedlistener (New Textwatcher () {@Override public void beforetextchanged (Charseque nce s, int start, int count, int after) {} @Override public void ontextchanged (charsequence s, int St Art, int before, int count) {} @Override public void aftertextchanged (Editable s) {//text changes, there are no sent search please
        Please cancel if (Mhandler.hasmessages (Msg_search)) {mhandler.removemessages (msg_search);
        //If the search history is directly displayed for null (Textutils.isempty (s)) {//showhistory ();
  }else {//Otherwise delay 500ms start search mhandler.sendemptymessagedelayed (msg_search,500);//automatic search function deletion}}});
      Private Handler Mhandler = new Handler () {@Override public void Handlemessage (msg) {//Search request Toast.maketext (mainactivity.this, "Search .....")
      ", Toast.length_short). Show ();
    Search (String.valueof (Medittextsearch.gettext ()));
  }
  };

private static final int msg_search = 1; 

==================================

Four, chronological history,

I have done two things in the encapsulated search method, and the server has always issued a search keyword request. Second, the synchronization will save the keyword to sharedprefrences (in the SP abbreviation) as a historical record.

A skip over, here mainly say two.

The keyword is saved to the SP in the form of Key-value, where I use the time in YYYYMMDDHHMMSS form as key, (for subsequent sorting), to deposit the keyword as value.

Because the history has to have a feeling that can be updated (the latest in front, enter previously searched keywords, such as jeans (originally the second), will update the record of the time, next time, look at the arrangement of jeans in the first place. ), so before I save the keyword every time, all of the data from the SP (back to the SP), traverse the returned map, whether there is a record of that value, and if so, delete it, because it is followed by a record of that value, so use this delete + insert operation, Implementation of the SP Update update function (the original SP only additions and deletions method).

Save history Code as follows:

Private SimpleDateFormat Mformat;
Mformat = new SimpleDateFormat ("Yyyymmddhhmmss");
/**
 * Save history to SP, key= current time (20160302133455, easy to sort), value= keyword
 * @param keyWords/
private void Savesearchhistory (String keyWords) {
  //save before querying for a record of this value in the SP, delete it. This guarantees that there will be no duplicate entries in the search history
  map<string, String> Historys = (map<string, string>) Searchhistoryutils.getall (getactivity ());
  For (map.entry<string, string> entry:historys.entrySet ()) {
    if (keywords.equals (Entry.getvalue ())) {
      Searchhistoryutils.remove (Getactivity (), Entry.getkey ());
    }
  Searchhistoryutils.put (Getactivity (), "" + Mformat.format (new Date ()), keyWords);
}

Query history

When you query, you return all the data in the SP and return a map collection. The keyset in the map collection is then removed, and the key is sorted because the key is inserted in the specified number format. Here is the ascending sort.

First calculate the keyset set length Keyleng, that is, the number of history records,

And then compared to the maximum number of bars to display (History_max, where our product defines 5),

If the number of history bars > The number of bars to display, take the history_max,5 bar. Otherwise, the number of Keyleng with the history record.

And then loop out the returned map collection, sorted by key in ascending order, after n data, added to the collection for display, here to judge, if the size of the data set to be displayed is not equal to 0, if there is a history, the Footerview (empty history) is displayed, otherwise it is not displayed.

The code is as follows:

/**
 * Displays a maximum of several historical records * *
private static final int history_max = 5;
/**
 * Search history from SP, and show by Time *
 *
private void Showsearchhistory () {
  map<string, string> hisall = (Map <string, string>) Searchhistoryutils.getall (getactivity ());
  Sort key in ascending order
  object[] keys = Hisall.keyset (). ToArray ();
  Arrays.sort (keys);
  int keyleng = keys.length;
  This calculates that if the number of history bars is greater than the maximum number of bars that can be displayed, the maximum number of bars is used to make the loop condition, preventing the number of history bars-the maximum number of negative values, the array bounds
  int hisleng = Keyleng > History_max? History_max:keyleng;
  for (int i = 1; I <= Hisleng i++) {
    mresults.add (Hisall.get (keys[keyleng-i)));
  Madapter.setdatas (mresults);
  If size is not 0 display Footerview
  mfooterview.setvisibility (0!=mresults.size)? View.VISIBLE:View.GONE);
}

================================

Five, Clear history

This is a simple feature that clears the data in the SP, but updates the ListView and Footerview visibility synchronously.

/**
 * Clear historical record
/private void Clearsearchhistory () {
  searchhistoryutils.clear (this);
  Also refreshes the history display page
  //mresults = new arraylist<> ();
  Madapter.setdatas (mresults);
  If size is not 0 display Footerview
  //mfooterview.setvisibility (0!=mresults.size)? View.VISIBLE:View.GONE);
}

==================================

Click the history entry to populate the EditText and perform the search function automatically.

There's nothing to say, click on the ListView settings, then set the content for EditText SetText (), and perform seach operations synchronously. Slightly.


==================================

Seven optimizations: In order to prevent more and more history bars, in this fragment OnDestroy () method, I called the deletion of the redundant history method, the number of elements in the SP has been controlled by the maximum number of bars to display:

Idea: If the map collection is larger than the max you want to display, then you want to remove the extra entries.

And then the query to display the history of logic, the first sort of key, delete, the key value is smaller than the extra few can.

The code is as follows:

/**
 * Delete Excess history
 * If the number of records is greater than the limited quantity (10), sort by key in ascending order, delete the previous
/private void Delmoresearchhistory () {

  map<string, string> Hisall = (map<string, string>) Searchhistoryutils.getall (this);
  if (Hisall.size () > History_max) {
    //Sort key in ascending order
    object[] keys = Hisall.keyset (). ToArray ();
    Arrays.sort (keys);
    LENGTH =, MAX = ten, I = 1,0,count =2;
    for (int i = keys.length-history_max-1 i > 1; i--) {
      Searchhistoryutils.remove (this, (String) keys[i]); 
   
    }
  }

}


   

================================================

This is my first small function in the new company, and I hereby record that

In fact, the function of the idea is generally as above, but with the SP will have some things to manually deal with, so some can say.

If you use the database to save the history, the direct use of select query criteria to sort time, delete also use the condition deletion, simpler.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.