1. 程式人生 > >使用SearchView+RecyclerView做搜尋框

使用SearchView+RecyclerView做搜尋框

安卓搜尋框分別使用了EditText+RecycleView和SearchView+RecycleView都實現了一遍 對比下兩種的區別!
首先是一張效果圖!
這裡寫圖片描述
一、EditText+RecycleView
先丟上程式碼!

Layout
<?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:orientation="vertical">
<EditText android:id="@+id/search_tag_input_edit" android:layout_width="match_parent" android:layout_height="30dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:background
="@drawable/shape_tag_search" android:layout_margin="8dp" android:hint="請輸入檢索Tag" android:drawableLeft="@mipmap/ic_search" android:drawablePadding="3dp" android:padding="8dp" android:maxLength="20" android:inputType="text" android:maxLines
="1" android:textSize="12sp" />
<android.support.v7.widget.RecyclerView android:id="@+id/search_tag_recycler" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@null" android:listSelector="@android:color/transparent" /> </LinearLayout>
Activity
package net.yeah.lililearn.searchrecyclerview;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

import net.yeah.lililearn.searchrecyclerview.adapter.SearchAdapter;
import net.yeah.lililearn.searchrecyclerview.model.SearchTag;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private EditText mSearchTagEdit;
    private RecyclerView mRecyclerView;
    private Handler handler = new Handler();
    private List<SearchTag> searchTagList;
    private SearchAdapter mAdapter;

    private Runnable delayRun = new Runnable() {
        @Override
        public void run() {
            searchTags(mSearchTagEdit.getText().toString().trim());
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initAdapter();
        setEvent();
    }

    private void initView() {
        mSearchTagEdit = (EditText) findViewById(R.id.search_tag_input_edit);
        mRecyclerView = (RecyclerView) findViewById(R.id.search_tag_recycler);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAnimation(null);
    }

    private void initAdapter() {
        searchTagList = new ArrayList<>();
        mAdapter = new SearchAdapter(searchTagList, this);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void setEvent() {
        mSearchTagEdit.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                //no-op
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                //no-op
            }

            @Override
            public void afterTextChanged(Editable editable) {
                //輸入完成後嚴重8毫秒在請求
                if (delayRun != null) {
                    handler.removeCallbacks(delayRun);
                }
                handler.postDelayed(delayRun, 800);
            }
        });

    }

    /**
     * 請求資料
     * @param searchTagName
     */
    private void searchTags(String searchTagName) {
        List<SearchTag> searchTags=new ArrayList<>();
        searchTags.add(new SearchTag("測試資料1"));
        searchTags.add(new SearchTag("測試資料2"));
        searchTags.add(new SearchTag("測試資料3"));
        searchTags.add(new SearchTag("測試資料4"));
        searchTags.add(new SearchTag("測試資料5"));
        searchTags.add(new SearchTag("測試資料6"));
        searchTags.add(new SearchTag("測試資料7"));
        searchTags.add(new SearchTag("測試資料8"));
        searchTags.add(new SearchTag("測試資料9"));
        searchTags.add(new SearchTag("測試資料10"));
        searchTagList.clear();
        searchTagList.addAll(searchTags);
        mAdapter.notifyDataSetChanged();
    }
}

adapter

package net.yeah.lililearn.searchrecyclerview.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebViewFragment;
import android.widget.RelativeLayout;
import android.widget.TextView;

import net.yeah.lililearn.searchrecyclerview.R;
import net.yeah.lililearn.searchrecyclerview.model.SearchTag;

import java.util.List;

import lombok.NonNull;


public class SearchAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int VIEW_TYPE_TOP = 0;
    private static final int VIEW_TYPE_ITEM = 1;
    private static final int VIEW_TYPE_END = 2;
    private static final int VIEW_TYPE_EMPTY = 3;

    private List<SearchTag> searchTagList;
    private Context context;

    public SearchAdapter(@NonNull List<SearchTag> Tags,
                         @NonNull Context context) {
        this.context = context;
        this.searchTagList = Tags;
        Log.e("11",searchTagList.toString());
    }

    @Override
    public int getItemViewType(int position) {
        Log.e("11",searchTagList.toString());
        if (searchTagList.isEmpty()) {
            if (position == 0) {
                return VIEW_TYPE_EMPTY;
            }
            return VIEW_TYPE_END;
        }
        if (position == 0) {
            return VIEW_TYPE_TOP;
        } else if (position == getItemCount() - 1) {
            return VIEW_TYPE_END;
        }
        return VIEW_TYPE_ITEM;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case VIEW_TYPE_TOP: {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_goods_tag_top, parent, false);
                return new GoodsTagTopHolder(view);
            }
            case VIEW_TYPE_ITEM: {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_goods_tag_item, parent, false);
                return new GoodsTagItemHolder(view);
            }
            case VIEW_TYPE_END: {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_goods_tag_end, parent, false);
                GoodsTagEndHolder holder = new GoodsTagEndHolder(view);
                holder.setEvent();
                return holder;
            }
            default: {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_goods_tag_empty, parent, false);
                return new EmptyViewHolder(view);
            }
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof GoodsTagItemHolder) {
            SearchTag searchTag = searchTagList.get(position - 1);
            GoodsTagItemHolder goodsTagItemHolder = (GoodsTagItemHolder) holder;
            goodsTagItemHolder.setData(searchTag);
            goodsTagItemHolder.setEvent(searchTag);
        }
    }

    @Override
    public int getItemCount() {
        if (searchTagList.isEmpty()) {
            return 2;
        }
        return searchTagList.size() + 2;
    }

    private class GoodsTagTopHolder extends RecyclerView.ViewHolder {
        GoodsTagTopHolder(View view) {
            super(view);
        }
    }

    private class GoodsTagItemHolder extends RecyclerView.ViewHolder {
        private TextView mGoodsTagItemTv;
        private RelativeLayout mGoodsTagItemLayout;

        GoodsTagItemHolder(View view) {
            super(view);
            mGoodsTagItemLayout = (RelativeLayout) view.findViewById(R.id.goods_tag_item_layout);
            mGoodsTagItemTv = (TextView) view.findViewById(R.id.goods_tag_item_tv);
        }

        public void setData(SearchTag searchTag) {
            String label = searchTag.getName();
            mGoodsTagItemTv.setText(label);
        }

        public void setEvent(SearchTag searchTag) {

        }
    }

    private class GoodsTagEndHolder extends RecyclerView.ViewHolder {
        private TextView mGoodsTagLinkTv;

        GoodsTagEndHolder(View view) {
            super(view);
            mGoodsTagLinkTv = (TextView) view.findViewById(R.id.goods_tag_link_tv);
        }

        public void setEvent() {
            mGoodsTagLinkTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }
    }

    private class EmptyViewHolder extends RecyclerView.ViewHolder {
        EmptyViewHolder(View itemView) {
            super(itemView);
            TextView textView = (TextView) itemView.findViewById(R.id.empty_text);
        }
    }
}

SearchView雖然是官方的但是一般不推薦使用!對於搜尋框的實現官方提供了SearchView但是很多坑需要去填推薦用EditText!

SearchView屬性

屬性名稱 相關方法 描述
android:iconifiedByDefault setIconifiedByDefault(boolean) 設定搜尋圖示是否顯示在搜尋框內
android:imeOptions setImeOptions(int) 設定輸入法搜尋選項欄位,預設是搜尋,可以是:下一頁、傳送、完成等
android:inputType setInputType(int) 設定輸入型別
android:maxWidth setMaxWidth(int) 設定最大寬度
android:queryHint setQueryHint(CharSequence) 設定查詢提示字串
setSubmitButtonEnabled (boolean enabled) 設定是否出現提交按鈕
package net.yeah.lililearn.searchrecyclerview.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;;
import android.text.TextUtils;
import android.widget.SearchView;

import net.yeah.lililearn.searchrecyclerview.R;
import net.yeah.lililearn.searchrecyclerview.adapter.SearchAdapter;
import net.yeah.lililearn.searchrecyclerview.model.SearchTag;

import java.util.ArrayList;
import java.util.List;

public class SearchViewActivity extends AppCompatActivity {
    private RecyclerView mSearchTagRecycler;
    private List<SearchTag> searchTagList;
    private SearchAdapter mAdapter;
    private SearchView mSearchTagView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        initView();
        initAdapter();
        setEvent();
    }

    private void initView() {
        mSearchTagView = (SearchView) findViewById(R.id.search_tag_view);
        mSearchTagRecycler = (RecyclerView) findViewById(R.id.search_tag_recycler);
        mSearchTagRecycler.setLayoutManager(new LinearLayoutManager(this));
        mSearchTagRecycler.setAnimation(null);
    }

    private void initAdapter() {
        searchTagList = new ArrayList<>();
        mAdapter = new SearchAdapter(searchTagList, this);
        mSearchTagRecycler.setAdapter(mAdapter);
    }

    private void setEvent() {
        mSearchTagView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                // 當點選搜尋按鈕時觸發該方法
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                // 當搜尋內容改變時觸發該方法
                if (!TextUtils.isEmpty(newText.trim())){
                    searchTags(newText.trim());

                }else{
                    searchTagList.clear();
                    mAdapter.notifyDataSetChanged();
                }
                return false;
            }
        });
    }


    /**
     * 請求資料
     * @param searchTagName
     */
    private void searchTags(String searchTagName) {
        List<SearchTag> searchTags=new ArrayList<>();
        searchTags.add(new SearchTag("測試資料1"));
        searchTags.add(new SearchTag("測試資料2"));
        searchTags.add(new SearchTag("測試資料3"));
        searchTags.add(new SearchTag("測試資料4"));
        searchTags.add(new SearchTag("測試資料5"));
        searchTags.add(new SearchTag("測試資料6"));
        searchTags.add(new SearchTag("測試資料7"));
        searchTags.add(new SearchTag("測試資料8"));
        searchTags.add(new SearchTag("測試資料9"));
        searchTags.add(new SearchTag("測試資料10"));
        searchTagList.clear();
        searchTagList.addAll(searchTags);
        mAdapter.notifyDataSetChanged();
    }
}
<?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:orientation="vertical">

    <SearchView
        android:id="@+id/search_tag_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:iconifiedByDefault="false"
        android:layout_margin="8dp"
        android:background="@drawable/shape_tag_search"
        android:queryHint="請輸入搜尋內容" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/search_tag_recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@null"
        android:listSelector="@android:color/transparent" />
</LinearLayout>

貼上效果圖
這裡寫圖片描述

專案中經常遇到的問題
1.放大鏡圖示的替換
2.X圖示的刪除
3.Text框下劃線刪除

總結:雖然官方的元件挺好使的,但是在專案中使用需要自己重寫一下才能使用。還是EditText比較適合!