模仿手机浏览器,点击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