项目需要,要求自定义一个searchview,其实Android自带的就有这个控件,而且做得很好,还有一些是通过修改样式来打造,笔者更喜欢把它抽出来成为一个控件,这样在以后的使用中会方便很多,于是在网上找了找资料,综合各大神的代码,给出自己的解决方案。

上效果图:
1、这个搜索框控件的布局并不是很复杂,左上方那个搜索的小图片是个ImageView,中间是EditText,最右边的小垃圾桶是个ImageView,只是在未输入搜索内容的时候visibility为gone,而搜索框下方是个gridview,gridview放的是搜索的热词,显示搜索内容的是一个webview,gridview是盖在webview上面的,之前有小伙伴问我怎么盖在另外一个控件上,原理很简单,把gridview的xml布局代码写在webview的xml布局代码下方就行。。。(很简单但是很有效)
2、这种由几个控件组成的自定义控件首先要做的是写布局文件,布局文件没什么好说的,上代码:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:id="@+id/search_area"android:background="@drawable/rect_gray"android:layout_height="wrap_content"><ImageViewandroid:layout_marginLeft="10dp"android:src="@android:drawable/ic_menu_search"android:id="@+id/search_iv_search"android:layout_gravity="left|center_vertical"android:layout_width="wrap_content"android:layout_height="wrap_content"/><EditTextandroid:id="@+id/search_et_input"android:layout_gravity="center_vertical"android:layout_margin="10dp"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:textSize="16sp"android:background="@null"android:imeOptions="actionSearch"android:inputType="text"android:textCursorDrawable="@null"android:hint="Google search"/><ImageViewandroid:visibility="gone"android:layout_marginRight="10dp"android:src="@android:drawable/ic_menu_delete"android:id="@+id/search_iv_delete"android:layout_gravity="right|center_vertical"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout><WebViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@id/search_area"android:id="@+id/search_wv_result"/><GridViewandroid:layout_below="@id/search_area"android:background="@drawable/rect_gray"android:numColumns="2"android:id="@+id/search_lv_tips"android:layout_width="match_parent"android:layout_height="wrap_content"></GridView ></RelativeLayout>
3、布局代码中就可以猜测到,我们将在一个LinearLayout或者一个RelativeLayout中去操作,我们让这个自定义控件继承自LinearLayout(当然也可以继承自RelativeLayout),这里可能需要频繁的调用开始搜索的代码,去做搜索onSearch()方法里的内容,还有就是每次搜索的时候都要隐藏键盘,
至于这个EditChangedListener,只是为了在在输入过程中动态的一些操作 ,笔者也是第一次使用TextWatcher。有gridview的地方就免不了adapter,通过外部设置给自定义控件一个adapter直接上代码吧:
public class YankeeSearchView extends LinearLayout implements View.OnClickListener {private EditText etInput;private ImageView ivDelete;private ImageView ivSearch;private Context mContext;private GridView lvTips;private WebView wvSearch;private ArrayAdapter<String> mHintAdapter;private SearchViewListener mListener;public YankeeSearchView(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;LayoutInflater.from(context).inflate(R.layout.search_layout, this);initViews();}private void initViews() {etInput = (EditText) findViewById(R.id.search_et_input);ivDelete = (ImageView) findViewById(R.id.search_iv_delete);ivSearch=(ImageView) findViewById(R.id.search_iv_search);lvTips = (GridView) findViewById(R.id.search_lv_tips);wvSearch= (WebView) findViewById(R.id.search_wv_result);wvSearch.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {lvTips.setVisibility(GONE);return false;}});lvTips.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {String text = lvTips.getAdapter().getItem(i).toString();etInput.setText(text);etInput.setSelection(text.length());lvTips.setVisibility(View.GONE);notifyStartSearching(text);}});ivDelete.setOnClickListener(this);ivSearch.setOnClickListener(this);etInput.addTextChangedListener(new EditChangedListener());etInput.setOnClickListener(this);etInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {@Overridepublic boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {if (actionId == EditorInfo.IME_ACTION_SEARCH) {lvTips.setVisibility(GONE);notifyStartSearching(etInput.getText().toString());}return true;}});}private void notifyStartSearching(String text){if (mListener != null) {mListener.onSearch(etInput.getText().toString());}InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);}public void setTipsHintAdapter(ArrayAdapter<String> adapter) {this.mHintAdapter = adapter;if (lvTips.getAdapter() == null) {lvTips.setAdapter(mHintAdapter);}}private class EditChangedListener implements TextWatcher {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {if (!"".equals(charSequence.toString())) {ivDelete.setVisibility(VISIBLE);lvTips.setVisibility(VISIBLE);} else {ivDelete.setVisibility(GONE);if (mHintAdapter != null) {lvTips.setAdapter(mHintAdapter);}lvTips.setVisibility(GONE);}}@Overridepublic void afterTextChanged(Editable editable) {}}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.search_et_input:lvTips.setVisibility(VISIBLE);break;case R.id.search_iv_delete:etInput.setText("");ivDelete.setVisibility(GONE);break;case R.id.search_iv_search:lvTips.setVisibility(GONE);notifyStartSearching(etInput.getText().toString());break;}}public void setSearchViewListener(SearchViewListener listener) {mListener = listener;}public interface SearchViewListener {void onSearch(String text);}public void setWebViewUrl(String url){if (url!=null){wvSearch.loadUrl(url);wvSearch.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});}}}
4、代码里都是一些隐藏显示的操作,比较重要的是对外的接口,还有就是setWebViewUrl()方法,用来对输入内容展开搜索。构造函数里传入了三个参数,传入一个布局文件,如果要自定义ite,可以写一个adapter,demo中为了简单,使用的是Android自带的只有一个textview的布局,而adapter使用的是ArrayAdapter<String>,的是再有就是通过简单修改代码就可以把gridview替换成ListView,笔者不操作了
5、至于调用,在activity_main布局文件中只要添加:
<com.yankee.yankeesearchview.YankeeSearchViewandroid:id="@+id/main_search_layout"android:layout_width="match_parent"android:layout_height="wrap_content"/>
6、在activity中,通过给searchview设置listener复写onSearch()方法,在方法里操作,别忘了通过setTipsHintAdapter()方法设置adapter:
public class MainActivity extends AppCompatActivity{private YankeeSearchView searchView;private ArrayAdapter<String> hintAdapter;private List<String> hintData;private static int HINT_SIZE=6;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initData();initView();}private void initView() {searchView = (YankeeSearchView) findViewById(R.id.main_search_layout);searchView.setSearchViewListener(new YankeeSearchView.SearchViewListener() {@Overridepublic void onSearch(String text) {Toast.makeText(MainActivity.this, "Search Complete", Toast.LENGTH_SHORT).show();searchView.setWebViewUrl("https://www.baidu.com/baidu?ie=utf-8&wd="+text);}});searchView.setTipsHintAdapter(hintAdapter);}private void initData() {hintData = new ArrayList<>(HINT_SIZE);for (int i = 1; i <= HINT_SIZE; i++) {hintData.add("Rio Olympic Games");}hintAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, hintData);}}
本文介绍了一种自定义SearchView的方法,包括布局设计、代码实现及如何集成搜索功能。

8113

被折叠的 条评论
为什么被折叠?



