先看張效果圖,
素材有點low,軟鍵盤右下角回車變成搜索按鈕。這種實現只需要在edittext上加入Android:imeOptions="actionSearch"即可,這個也根據版本的2.3以上就必須添加android:singleLine="true",這個可以理解,因爲單行爲true時,回車就不會起作用。
先看下整體的佈局
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="#14141F"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="6dp"
android: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="@mipmap/icon"/>
<RelativeLayout
android:id="@+id/rl_search_layout"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/et_search"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:background="@null"
android:hint="輸入商品名或者店鋪名稱"
android:imeOptions="actionSearch"
android:singleLine="true"
android:textColor="#FFFFFF"
android:textColorHint="#7F7F7F"
android:textSize="14sp" />
</RelativeLayout>
<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_vertical"
android:text="取消"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
<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="@mipmap/brand_search_history_icon"
android:drawablePadding="10dp"
android:text="歷史記錄"
android:textColor="#333333" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dfdfdf" />
<ListView
android:id="@+id/listView"
android:divider="@null"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
</LinearLayout>
佈局大體就爲這樣,整個流程就是當用戶在輸入框輸入內容時,點擊軟鍵盤的搜索按鈕,會做出一定的邏輯處理,Demo就Toast一句話而已。保存搜索內容作爲搜索歷史記錄,在保存的時候採用的sp(SharedPreferences)來實現。
需要注意的是 setOnEditorActionListener這個方法,並不是在我們點擊EditText的時候觸發,也不是在我們對EditText進行編輯時觸發,而是在我們編輯完之後點擊軟鍵盤上的回車鍵纔會觸發。我們把回車鍵改爲搜索鍵,所以當我們點擊搜索時,監聽方法會觸發,實現搜索的具體邏輯。
//監聽軟鍵盤輸入法按下【搜索】事件。
etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// 先隱藏鍵盤
((InputMethodManager) etSearch.getContext().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
//搜索具體邏輯
Toast.makeText(getApplicationContext(),"已經跳轉到"+etSearch.getText()+"界面",Toast.LENGTH_SHORT).show();
//保存歷史記錄
saveSearchHistory(String.valueOf(etSearch.getText()));
return true;
}
return false;
}
});
接下來看下是如何保存的呢,採用鍵值對的方式,key爲搜索時候的時間戳,value則爲搜索時候的關鍵字,採用時間戳的做法相對於後期實現歷史記錄動態改變實現比較方便,按時間戳排序即可。所謂的動態改變就是原本爲第二個的歷史記錄,我們再次搜索,會更改爲最新的。但保存的時候要先做一步判斷,查詢一些是否存在,存在我們則刪除,然後在put添加。下面代碼就是採用遍歷Map的效率高的一種方法entrySet(),entrySet是 鍵-值 對的集合,Set裏面的類型是Map.Entry,
舉個例子我們來看下entrySet()方法兩種遍歷:
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("1", "小王");
map.put("2", "小陳");
map.put("3", "小李");
/*方法一 :迭代程序*/
System.out.println("方法一:");
Iterator iterator=map.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, String> entry= (Entry<String, String>) iterator.next();
System.out.println("key:"+entry.getKey()+" value"+entry.getValue());
}
/*方法二*/
System.out.println("方法二:");
for (Map.Entry<String, String> m : map.entrySet()) {
System.out.println("key:"+m.getKey()+" value"+m.getValue());
}
}
private void saveSearchHistory(String keyWords) {
//保存之前要先查詢sp中是否有該value的記錄,有則刪除.這樣保證搜索歷史記錄不會有重複條目
Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());
for (Map.Entry<String, String> entry : historys.entrySet()) {
if(keyWords.equals(entry.getValue())){
SearchHistoryUtils.remove(getApplicationContext(),entry.getKey());
}
}
SearchHistoryUtils.put(getApplicationContext(), "" + mFormat.format(new Date()), keyWords);
}
歷史記錄保存我們實現了,那麼接下來就是展示的了,根據搜索的時間先後排序來展示的,當不存在歷史記錄時,隱藏footView,也就是清空歷史記錄那塊佈局。
private void showSearchHistory() {
Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());
//將key排序升序
Object[] keys = hisAll.keySet().toArray();
Arrays.sort(keys);
int keyLeng = keys.length;
//這裏計算 如果歷史記錄條數是大於 可以顯示的最大條數,則用最大條數做循環條件,防止歷史記錄條數-最大條數爲負值,數組越界
int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng;
for (int i = 1; i <= hisLeng; i++) {
mResults.add(hisAll.get(keys[keyLeng - i]));
}
mListView.setAdapter(mAdapter);
//如果size不爲0 顯示footerview
mFooterView.setVisibility(0!=mResults.size()? View.VISIBLE:View.GONE);
}
整個Activity
public class MainActivity extends AppCompatActivity {
private EditText etSearch;
private static final int MSG_SEARCH = 1;
private static final int HISTORY_MAX = 5;//最多顯示五條歷史記錄
private Context mContext;
private SimpleDateFormat mFormat;
private ListView mListView;
private View mFooterView;
private MyAdapter mAdapter;
private TextView tvCancel;
List<String> mResults = new ArrayList<String>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initListener();
showSearchHistory();
}
private void initView() {
etSearch=(EditText)findViewById(R.id.et_search);
tvCancel= ((TextView) findViewById(R.id.tv_cancel));
mFormat = new SimpleDateFormat("yyyyMMddHHmmss");
mListView=(ListView)findViewById(R.id.listView);
LayoutInflater layoutInflater =
(LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
mFooterView = layoutInflater.inflate(R.layout.footview, null);
mListView.addFooterView(mFooterView);
mAdapter=new MyAdapter(this);
}
private void initListener() {
//監聽軟鍵盤輸入法按下【搜索】事件。
etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// 先隱藏鍵盤
((InputMethodManager) etSearch.getContext().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
//搜索具體邏輯
Toast.makeText(getApplicationContext(),"已經跳轉到"+etSearch.getText()+"界面",Toast.LENGTH_SHORT).show();
//搜索請求轉交給函數去處理
saveSearchHistory(String.valueOf(etSearch.getText()));
return true;
}
return false;
}
});
// 清空歷史記錄點擊事件
mFooterView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clearsearchHistory();
}
});
//取消按鈕點擊事件
tvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
etSearch.setText("");
}
});
}
/**
*/
private void saveSearchHistory(String keyWords) {
//保存之前要先查詢sp中是否有該value的記錄,有則刪除.這樣保證搜索歷史記錄不會有重複條目
Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());
for (Map.Entry<String, String> entry : historys.entrySet()) {
if(keyWords.equals(entry.getValue())){
SearchHistoryUtils.remove(getApplicationContext(),entry.getKey());
}
}
SearchHistoryUtils.put(getApplicationContext(), "" + mFormat.format(new Date()), keyWords);
}
private void showSearchHistory() {
Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext());
//將key排序升序
Object[] keys = hisAll.keySet().toArray();
Arrays.sort(keys);
int keyLeng = keys.length;
//這裏計算 如果歷史記錄條數是大於 可以顯示的最大條數,則用最大條數做循環條件,防止歷史記錄條數-最大條數爲負值,數組越界
int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng;
for (int i = 1; i <= hisLeng; i++) {
mResults.add(hisAll.get(keys[keyLeng - i]));
}
mListView.setAdapter(mAdapter);
//如果size不爲0 顯示footerview
mFooterView.setVisibility(0!=mResults.size()? View.VISIBLE:View.GONE);
}
private void clearsearchHistory() {
SearchHistoryUtils.clear(this);
//同時刷新歷史記錄顯示頁面
mResults = new ArrayList<>();
mListView.setAdapter(mAdapter);
//mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,mResults));
//如果size不爲0 顯示footerview
mFooterView.setVisibility(0!=mResults.size()?View.VISIBLE:View.GONE);
}
public class MyAdapter extends BaseAdapter {
private LayoutInflater mInflater = null;
private MyAdapter(Context context)
{
//根據context上下文加載佈局,這裏的是Demo17Activity本身,即this
this.mInflater = LayoutInflater.from(context);
}
public int getCount() {
return mResults.size();
}
@Override
public Object getItem(int i) {
return mResults.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
ViewHolder holder;
if(convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.lvitem, null);
holder.title= ((TextView) convertView.findViewById(R.id.info));
convertView.setTag(holder);
}else
{
holder = (ViewHolder)convertView.getTag();
}
holder.title.setText(mResults.get(i));
return convertView;
}
}
static class ViewHolder
{
public TextView title;
}
}
就是一個listView展示歷史記錄,其中有一個item佈局,和一個footView佈局
footview.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/ivClearAll"
android:layout_width="15dp"
android:layout_height="15dp"
android:src="@mipmap/clear"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="177dp"
android:layout_marginTop="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清空歷史記錄"
android:textSize="15sp"
android:layout_alignTop="@+id/ivClearAll"
android:layout_toEndOf="@+id/ivClearAll" />
</RelativeLayout>
lvitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/info"
android:layout_marginTop="12dp"
android:layout_marginLeft="35dp"
android:layout_width="wrap_content"
android:text="電子商務"
android:textColor="#333333"
android:layout_height="40dp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#dfdfdf" />
</LinearLayout>
工具類傳送門 http://download.csdn.net/detail/u012896330/9728714