2015-01-31 488 views
1

[解決]自動完成搜索查看是否有可能使SearchViewActionBar(android.support.v7.app)(android.support.v7.widget)像MultiAutoCompleteTextView與自定義分隔符

在自定義分隔符之後建議這樣的詞。

我沒有延伸MultiAutoCompleteTextView,因爲我不想丟失圖標,「X」按鈕等功能。

enter image description here

UPDATE:

我試圖擴大SearchView

public class MultiAutoCompleteSearchView extends android.support.v7.widget.SearchView { 

    private MultiAutoCompleteSearchView.SearchAutoComplete mSearchAutoComplete; 

    public static class SearchAutoComplete extends android.support.v7.widget.SearchView.SearchAutoComplete { 

     private String mSeparator = "+"; 

     public SearchAutoComplete(Context context) { 
      super(context); 
     } 
     public SearchAutoComplete(Context context, AttributeSet attrs) { 
      super(context, attrs); 
     } 
     public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) { 
      super(context, attrs, defStyle); 
     } 

     @Override 
     protected void replaceText(CharSequence text) { 
      String newText = getText().toString(); 
      if (newText.contains(mSeparator)) { 
       int lastIndex = newText.lastIndexOf(mSeparator); 
       newText = newText.substring(0, lastIndex + 1) + text.toString(); 
      } else { 
       newText = text.toString(); 
      } 
      super.replaceText(newText); 
     } 

     @Override 
     protected void performFiltering(CharSequence text, int keyCode) { 
      String newText = text.toString(); 
      if (newText.indexOf(mSeparator) != -1) { 
       int lastIndex = newText.lastIndexOf(mSeparator); 
       if (lastIndex != newText.length() - 1) { 
        newText = newText.substring(lastIndex + 1).trim(); 
        if (newText.length() >= getThreshold()) { 
         text = newText; 
        } 
       } 
      } 
      super.performFiltering(text, keyCode); 
     } 
    } 

    public void initialize() { 
     mSearchAutoComplete = (MultiAutoCompleteSearchView.SearchAutoComplete) 
       findViewById(android.support.v7.appcompat.R.id.search_src_text); 
     this.setAdapter(null); 
     this.setOnItemClickListener(null); 
    } 

    public MultiAutoCompleteSearchView(Context context) { 
     super(context); 
     initialize(); 
    } 

    public MultiAutoCompleteSearchView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initialize(); 
    } 

    public MultiAutoCompleteSearchView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     initialize(); 
    } 

    public void setOnItemClickListener(AdapterView.OnItemClickListener listener) { 
     mSearchAutoComplete.setOnItemClickListener(listener); 
    } 

    public void setAdapter(ArrayAdapter<?> adapter) { 
     mSearchAutoComplete.setAdapter(adapter); 
    } 
} 

和XML文件菜單。

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     xmlns:tools="http://schemas.android.com/tools" 
     tools:context=".SearchActivity"> 
    <item android:id="@+id/action_search" 
      android:title="@string/action_search" 
      android:icon="@drawable/ic_action_search" 
      app:showAsAction="ifRoom|collapseActionView" 
      app:actionViewClass="cullycross.com.searchview.MultiAutoCompleteSearchView" /> 
</menu> 

和活動方法:

public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_search, menu); 

    final MenuItem searchItem = menu.findItem(R.id.action_search); 
    final MultiAutoCompleteSearchView searchView = (MultiAutoCompleteSearchView) 
      MenuItemCompat.getActionView(searchItem); 
    searchView.setQueryHint("Type any word"); 
    MultiAutoCompleteSearchView.SearchAutoComplete searchAutoComplete = 
      (MultiAutoCompleteSearchView.SearchAutoComplete)searchView 
        .findViewById(R.id.search_src_text); 
    searchAutoComplete.setAdapter(new ArrayAdapter<String>(
      this, 
      android.R.layout.simple_dropdown_item_1line, 
      options 
    )); 
    return true; 
} 

但由於某些原因我在這裏得到了NPE:searchView.setQueryHint("Type any word");,所以這意味着,getActionView回報

回答

1

很多時間都過去了,我發現了一個解決方案:

定義適配器:

public class DelimiterAdapter extends ArrayAdapter<String> implements Filterable { 
    private final static String [] options = { 
     "Apple","Mango","Peach","Banana","Orange","Grapes","Watermelon","Tomato" 
    }; 
    private final LayoutInflater mInflater; 
    private List<String> mSubStrings; 

    private String mMainString; 
    public String getMainString() { return mMainString; } 

    private AmazingFilter mFilter; 

    public DelimiterAdapter(Context context, int resource) { 
     super(context, -1); 
     mInflater = LayoutInflater.from(context); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     final TextView tv; 
     if (convertView != null) { 
      tv = (TextView) convertView; 
     } else { 
      tv = (TextView) mInflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false); 
     } 
     tv.setText(getItem(position)); 
     return tv; 
    } 

    @Override 
    public int getCount() { 
     return mSubStrings.size(); 
    } 

    @Override 
    public String getItem(int position) { 
     return mSubStrings.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 


    @Override 
    public Filter getFilter() { 
     if(mFilter == null) { 
      mFilter = new AmazingFilter(); 
     } 
     return mFilter; 
    } 

    private class AmazingFilter extends Filter { 

     private final static String DELIMITER = "+"; 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      final FilterResults filterResults = new FilterResults(); 
      String request; 
      mSubStrings = new ArrayList<String>(); 
      if(constraint != null) { 
       request = constraint.toString(); 

       //cuts the string with delimiter 
       if (request.contains(DELIMITER) && 
         request.lastIndexOf(DELIMITER) != request.length() - 1) { 
        final String[] splitted = request.split("\\" + DELIMITER); 
        request = splitted[splitted.length - 1].trim(); 

        //save string before delimiter 
        int index = constraint.toString().lastIndexOf(request); 
        mMainString = constraint.toString().substring(0, index); 
       } else { 
        request = request.trim(); 
        mMainString = ""; 
       } 


       //checks for substring of any word in the dictionary 
       for(String s : options) { 
        if(s.contains(request)) { 
         mSubStrings.add(s); 
        } 
       } 
      } 
      filterResults.values = mSubStrings; 
      filterResults.count = mSubStrings.size(); 
      return filterResults; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      clear(); 
      for (String request : (ArrayList<String>)results.values) { 
       add(request); 
      } 
      if (results.count > 0) { 
       notifyDataSetChanged(); 
      } else { 
       notifyDataSetInvalidated(); 
      } 
     } 
    } 
} 

擴展SearchView

public class MultiAutoCompleteSearchView extends android.support.v7.widget.SearchView { 

    private SearchAutoComplete mSearchAutoComplete; 

    public void initialize() { 
     mSearchAutoComplete = (SearchAutoComplete) 
      findViewById(android.support.v7.appcompat.R.id.search_src_text); 
     this.setAdapter(null); 
     this.setOnItemClickListener(null); 
    } 

    public MultiAutoCompleteSearchView(Context context) { 
     super(context); 
     initialize(); 
    } 

    public MultiAutoCompleteSearchView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initialize(); 
    } 

    public MultiAutoCompleteSearchView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     initialize(); 
    } 

    public void setOnItemClickListener(AdapterView.OnItemClickListener listener) { 
     mSearchAutoComplete.setOnItemClickListener(listener); 
    } 

    public void setAdapter(ArrayAdapter<?> adapter) { 
     mSearchAutoComplete.setAdapter(adapter); 
    } 
} 

活動方法onCreateMenuOptions

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_search, menu); 

    final MenuItem searchItem = menu.findItem(R.id.action_search); 

    final MultiAutoCompleteSearchView searchView = (MultiAutoCompleteSearchView) 
     MenuItemCompat.getActionView(searchItem); 

    searchView.setQueryHint("Type any word"); 

    MultiAutoCompleteSearchView.SearchAutoComplete searchAutoComplete = 
     (MultiAutoCompleteSearchView.SearchAutoComplete)searchView 
       .findViewById(R.id.search_src_text); 
    //since words are very short 
    searchAutoComplete.setThreshold(1); 

    searchAutoComplete.setAdapter(new DelimiterAdapter( 
      this, 
      android.R.layout.simple_dropdown_item_1line 
    )); 

    searchView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 

      String stringBefore, newString; 
      stringBefore = ((DelimiterAdapter)parent.getAdapter()).getMainString(); 
      newString = parent.getAdapter().getItem(position).toString(); 

      searchView.setQuery(stringBefore+newString, false); 
     } 
    }); 


    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 
     @Override 
     public boolean onQueryTextSubmit(String s) { 
      if(s.length() > 0) { 
       mFindString = s; 

       // do smth with string 
       return true; 
      } 
      return false; 
     } 

     @Override 
     public boolean onQueryTextChange(String s) { 
      return false; 
     } 
    }); 

    return true; 
} 

菜單的XML文件:

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     xmlns:tools="http://schemas.android.com/tools" 
     tools:context=".SearchActivity"> 
    <item android:id="@+id/action_search" 
     android:title="@string/action_search" 
     android:icon="@drawable/ic_action_search" 
     app:showAsAction="ifRoom|collapseActionView" 
     app:actionViewClass="cullycross.com.searchview.MultiAutoCompleteSearchView" /> 
</menu>