模仿手机浏览器,点击Edittext,同时出现搜索历史和软键盘
来源:互联网 发布:qq降龙刷奇缘软件 编辑:程序博客网 时间:2024/05/17 09:18
最近项目中有个需求,在点击一个edittext的输入框的时候,要出现一个展示搜索历史的view,如果有2条以上的,就先显示2条,点击对应按钮,可以展示全部搜索历史。最多保存、显示5条。最开始的时候,打算用popupwindow,但是,会和系统的软键盘冲突。在onclick事件中,如果要想同时弹出搜索历史popupwindow和软键盘,会导致出现一个问题:点击edittext的时候,显示中文输入法键盘,然后,自动切换到英文输入法。此时,还不能再输入内容。用了很多办法,哪怕是handler的延时弹出popupwindow,也不行。最后,决定,不用popupwindow。就是点击的时候,出现一个listview,软键盘会自动出现。
预览图:
tips:主布局中的“保存”等按钮,不要用Button,要不然,listview出现的时候,反而会被这些Button压在下面。但是用其他的,就不会
具体代码实现(不再多做说明了,注释很详细了):
Listview适配器的item用的布局
option_item_2:
<?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="wrap_content" android:orientation="vertical" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00aa00" android:gravity="center_vertical" > <ImageView android:id="@+id/delImage" android:layout_width="20dp" android:layout_height="20dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="10dp" android:src="@mipmap/ic_launcher" android:textSize="15dp"/> <TextView android:id="@+id/item_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_toLeftOf="@id/delImage" android:paddingBottom="10dp" android:paddingLeft="5dp" android:paddingTop="10dp" android:textColor="#333333" android:textSize="14sp"/> </RelativeLayout> <RelativeLayout android:id="@+id/show_all_history_or_cancel" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/show_all_history" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dp" android:paddingBottom="10dp" android:paddingTop="10dp" android:text="全部搜索记录" android:textColor="#888888" android:textSize="14sp"/> <TextView android:id="@+id/cancel_history" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_gravity="center" android:layout_marginRight="10dp" android:paddingBottom="10dp" android:paddingTop="10dp" android:text="关闭" android:textColor="#888888" android:textSize="14sp"/> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#666666" /></LinearLayout>
OptionsAdapter_2
package com.chen.customviewdemo.adapter;import android.app.Activity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;import com.chen.customviewdemo.R;import com.chen.customviewdemo.listener.HandleListviewItemListener;import com.chen.customviewdemo.utils.CHEN;import java.util.ArrayList;/** * 适配器 */public class OptionsAdapter_2 extends BaseAdapter { private ArrayList<String> list = new ArrayList<String>(); private Activity activity = null; private HandleListviewItemListener handleListviewItemListener; /** * 自定义构造方法 * * @param activity * @param list */ public OptionsAdapter_2(Activity activity, HandleListviewItemListener listener, ArrayList<String> list) { this.activity = activity; this.list = list; handleListviewItemListener = listener; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } class ViewHolder { TextView textView; ImageView imageView; TextView show_all_history; TextView cancel_history; RelativeLayout show_all_history_or_cancel; } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); //下拉项布局 convertView = LayoutInflater.from(activity).inflate(R.layout.option_item_2, null); holder.textView = (TextView) convertView.findViewById(R.id.item_text); holder.imageView = (ImageView) convertView.findViewById(R.id.delImage); holder.show_all_history = (TextView) convertView.findViewById(R.id.show_all_history); holder.cancel_history = (TextView) convertView.findViewById(R.id.cancel_history); holder.show_all_history_or_cancel = (RelativeLayout) convertView.findViewById(R.id.show_all_history_or_cancel); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } if (CHEN.HideShowAllSearchHistory && list.size() == 2 && position == 1) { holder.show_all_history_or_cancel.setVisibility(View.VISIBLE); } else { holder.show_all_history_or_cancel.setVisibility(View.GONE); } if (position == list.size() - 1) { holder.show_all_history_or_cancel.setVisibility(View.VISIBLE); if (CHEN.HideShowAllSearchHistory) { //说明有2个以上的搜索历史记录 holder.show_all_history.setVisibility(View.VISIBLE); } else { holder.show_all_history.setVisibility(View.GONE); } } /** * 显示全部搜索记录 */ holder.show_all_history.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { handleListviewItemListener.handleListviewItem("showAllSearchHistory", -1); } }); /** * 关闭搜索记录提示 */ holder.cancel_history.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { handleListviewItemListener.handleListviewItem("cancelSearchHistoryTip", -1); } }); holder.textView.setText(list.get(position)); //为下拉框选项文字部分设置事件,最终效果是点击将其文字填充到文本框 holder.textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { handleListviewItemListener.handleListviewItem("setSelestData", position); } }); //为下拉框选项删除图标部分设置事件,最终效果是点击将该选项删除 holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!CHEN.HideShowAllSearchHistory) { handleListviewItemListener.handleListviewItem("delSelestData", position); } } }); return convertView; }}
Activity的布局activity_main_9
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#EEEED1" > <EditText android:id="@+id/edittext" android:layout_width="200dp" android:layout_height="40dp" android:layout_marginLeft="30dp" android:layout_marginTop="50dp" android:background="#dedede" android:paddingLeft="3dp" android:singleLine="true"/> <TextView android:id="@+id/save" android:layout_width="wrap_content" android:layout_height="45dp" android:layout_below="@id/edittext" android:layout_marginLeft="30dp" android:layout_marginTop="30dp" android:text="保存" android:textColor="#000000" android:textSize="20sp"/> <TextView android:id="@+id/show" android:layout_width="wrap_content" android:layout_height="45dp" android:layout_below="@id/save" android:layout_marginLeft="30dp" android:layout_marginTop="30dp" android:text="展示" android:textColor="#000000" android:textSize="20sp"/> <TextView android:id="@+id/clear" android:layout_width="wrap_content" android:layout_height="45dp" android:layout_below="@id/show" android:layout_marginLeft="30dp" android:layout_marginTop="30dp" android:text="清空" android:textColor="#000000" android:textSize="20sp"/> <ListView android:id="@+id/search_history_lv" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_below="@id/edittext" android:layout_marginLeft="30dp" android:background="#ffffff" android:visibility="gone"/></RelativeLayout>
MainActivity_9
package com.chen.customviewdemo;import android.app.Activity;import android.os.Bundle;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.widget.EditText;import android.widget.ListView;import android.widget.TextView;import com.chen.customviewdemo.adapter.OptionsAdapter_2;import com.chen.customviewdemo.listener.HandleListviewItemListener;import com.chen.customviewdemo.utils.CHEN;import com.chen.customviewdemo.utils.SharedPreferencesUtil;import com.chen.customviewdemo.utils.Utils;import java.util.ArrayList;public class MainActivity_9 extends Activity implements View.OnClickListener, HandleListviewItemListener { //下拉框选项数据源 private ArrayList<String> datas; //文本框 private EditText et; //保存输入过的数据 private TextView save_input_data; //用于展示数据的 private TextView show_pop; //清理数据 private TextView clear; //保存搜索数据 SharedPreferencesUtil spUtil; //展示搜索历史的listview ListView search_history_lv; //适配器 private OptionsAdapter_2 adapter; /** * 临时存放数据的 */ private ArrayList<String> tempDatas; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_9); spUtil = new SharedPreferencesUtil(MainActivity_9.this); datas = new ArrayList<String>(); tempDatas = new ArrayList<String>(); search_history_lv = (ListView) findViewById(R.id.search_history_lv); adapter = new OptionsAdapter_2(this, this, datas); search_history_lv.setAdapter(adapter); //初始化界面组件 et = (EditText) findViewById(R.id.edittext); clear = (TextView) findViewById(R.id.clear); clear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { datas.clear(); spUtil.saveSearchKeyHistory(""); } }); save_input_data = (TextView) findViewById(R.id.save); //设置点击事件,恢复下拉框列表数据,没有什么作用,纯粹是为了方便多看几次效果而设置 save_input_data.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //编辑框输入的数据 String willSave = et.getText().toString().trim(); if (!TextUtils.isEmpty(willSave)) { String saveData = spUtil.getSearchKeyHistory(); if (TextUtils.isEmpty(saveData)) { //说明之前没有搜索历史,直接存放当前的搜索数据 spUtil.saveSearchKeyHistory(willSave); } else { if (!Utils.isContainsStr(saveData, willSave)) { //已有数据中,不包含新的搜索内容,把最新搜索内容加到最前面 saveData = willSave + "-" + saveData; } else { //已有数据中,包含新的搜索内容,要重新排序,把最新的搜索内容,放在最前面 String[] oldOrder = saveData.split("-"); int equaseIndex = 0; for (int i = 0; i < oldOrder.length; i++) { if (oldOrder[i].equals(willSave)) { equaseIndex = i; break; } } if (equaseIndex != 0) { //新的搜索内容,不在保存数据的第一条。(如果在第一条,就不用处理了) saveData = oldOrder[equaseIndex]; for (int j = 0; j < equaseIndex; j++) { saveData = saveData + "-" + oldOrder[j]; } for (int k = equaseIndex + 1; k < oldOrder.length; k++) { saveData = saveData + "-" + oldOrder[k]; } } } //项目中,输入框默认的一次最多输入数据是20个字。5条数据是100字。这里再多加点。这里正确的处理,应该是保证只保存5条。这里偷个懒,不在详细写了。 if (saveData.length() > 150) { saveData = saveData.substring(0, 150); } spUtil.saveSearchKeyHistory(saveData); } } } }); show_pop = (TextView) findViewById(R.id.show); show_pop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showSearchHistory(); } }); et.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("chen", "onClick---"); if (TextUtils.isEmpty(et.getText().toString().trim())) { showSearchHistory(); } } }); } /** * 显示搜索历史 */ public void showSearchHistory() { datas.clear(); String data = spUtil.getSearchKeyHistory(); if (!TextUtils.isEmpty(data)) { if (data.contains("-")) { String[] dList = data.split("-"); int length = dList.length > 5 ? 5 : dList.length; for (int i = 0; i < length; i++) { if (!TextUtils.isEmpty(dList[i])) { datas.add(dList[i]); } } } else { datas.add(data); } } if (datas != null && datas.size() > 0) { if (datas.size() > 2) { CHEN.HideShowAllSearchHistory = true; tempDatas.clear(); tempDatas.addAll(datas); //如果有多条,默认显示前2条。上面已经保存到临时的里面了,这里就可以把2条以后的数据清理掉 for (int i = datas.size() - 1; i >= 2; i--) { datas.remove(i); } } adapter.notifyDataSetChanged(); search_history_lv.setVisibility(View.VISIBLE); } } @Override public void onClick(View v) { } @Override public void handleListviewItem(String flag, int index) { //给Edittext设置选中的内容 if ("setSelestData".equals(flag)) { et.setText(datas.get(index)); search_history_lv.setVisibility(View.GONE); } //删除选择条目 if ("delSelestData".equals(flag)) { datas.remove(index); tempDatas.clear(); tempDatas.addAll(datas); //刷新下拉列表 adapter.notifyDataSetChanged(); if (datas == null || datas.size() == 0) { spUtil.saveSearchKeyHistory(""); } else { if (datas.size() == 1) { spUtil.saveSearchKeyHistory(datas.get(0)); } else { String temp = ""; for (int j = 0; j < datas.size(); j++) { temp = temp + datas.get(j) + "-"; } if (temp.endsWith("-")) { temp = temp.substring(0, temp.length() - 1); } spUtil.saveSearchKeyHistory(temp); } } } //展示所有搜索历史 if ("showAllSearchHistory".equals(flag)) { CHEN.HideShowAllSearchHistory = false; datas.clear(); datas.addAll(tempDatas); adapter.notifyDataSetChanged(); } //关闭展示所有搜索历史 if ("cancelSearchHistoryTip".equals(flag)) { CHEN.HideShowAllSearchHistory = false; search_history_lv.setVisibility(View.GONE); } }}
处理listview中某个条目的监听接口
HandleListviewItemListener
package com.chen.customviewdemo.listener;/** * 处理listview中某个条目的监听接口 */public interface HandleListviewItemListener { void handleListviewItem(String flag, int index);}
用到的工具:
package com.chen.customviewdemo.utils;import android.app.Activity;import android.text.TextUtils;import android.util.DisplayMetrics;/** * 工具类 */public class Utils { /** * 判断一个大的string里面,是否包含另一个小的string * * @param mianStr 大的string(主string) * @param data 要判断的string * @return true表示包含,false表示不包含 */ public static boolean isContainsStr(String mianStr, String data) { try { if (checkStringIsEmpty(mianStr) || checkStringIsEmpty(data)) { return false; } else { if (mianStr.contains("-")) { boolean b = false; String[] arr = mianStr.split("-"); for (int i = 0; i < arr.length; i++) { if (data.equals(arr[i])) { b = true; } } return b; } else { if (mianStr.equals(data)) { return true; } else { return false; } } } } catch (Exception e) { return false; } }}
全局变量
package com.chen.customviewdemo.utils;/** * 用于保存全局变量值 */public class CHEN { /** * 是否隐藏“全部搜索记录” */ public static boolean HideShowAllSearchHistory = false;}
0 0
- 模仿手机浏览器,点击Edittext,同时出现搜索历史和软键盘
- 点击Edittext,同时出现搜索历史展示和系统软键盘(升级版)
- EditText点击的时候软键盘上出现搜索按钮
- EditText点击的时候软键盘上出现搜索按钮
- EditText在手机弹出的软键盘中,将回车键变为搜索键和点击搜索键时,执行2次搜索解决
- 让手机软键盘出现“搜索”按钮
- android在点击搜索按钮同时关闭软键盘
- 手机软键盘搜索按钮实现点击搜索功能
- Android点击EditText之外的地方隐藏软键盘同时使EditText失去焦点
- 点击返回键,同时隐藏输入区域和软键盘
- EditText和软键盘
- 点击EditText不弹出软键盘
- 点击EditText隐藏软键盘代码
- 点击editText无法弹出软键盘
- EditText 点击其它区域收起软键盘
- 点击Edittext,禁止软键盘弹出
- 让EditText响应软键盘搜索
- Android EditText 软键盘搜索事件
- USB PL2102 驱动
- 音视频会议理论网络参数
- RSA加密算法原理
- sigqueue函数 进程间通信 信号的发送携带数据
- PathEffect()详解
- 模仿手机浏览器,点击Edittext,同时出现搜索历史和软键盘
- 信号发送函数sigqueue和信号安装函数sigaction
- centos6下配置本地yum源
- 【DP经典】noi openjudge 2.6 最长上升子序列
- mongodb 随机获取一条记录的方法
- TOMCAT启动时报:Last packet sent to the server was 0 ms ago
- 性能测试———为什么需要进行性能测试?
- c++中使用libcurl库进行http网络编程
- 源文件与头文件的功能与区别