热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android实现搜索历史功能

这篇文章主要为大家详细介绍了Android实现搜索历史功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的

本文实例为大家分享了Android实现搜索历史的具体代码,供大家参考,具体内容如下

SharedPreferences实现本地搜索历史功能,覆盖搜索重复的文本,可清空 

1. 判断搜索内容是否含表情,不需要可以不判断

/**
  * 校验字符串是否含有表情
  * @param content
  * @return
  */
 public static boolean hasEmoji(String content){
 
  Pattern pattern = Pattern.compile("[ud83cudc00-ud83cudfff]|[ud83dudc00-ud83dudfff]|[u2600-u27ff]");
  Matcher matcher = pattern.matcher(content);
  if(matcher .find()){
   return true;
  }
  return false;
}

2.软键盘工具类弹出、关闭,不需要可以不判断

public class KeyBoardUtils {
 
 /**
  * 打开软键盘
  *
  * @param editText
  * @param context
  */
 public static void openKeybord(EditText editText, Context context) {
  InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
  imm.showSoftInput(editText, InputMethodManager.RESULT_SHOWN);
  imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
 }
 
 /**
  * 关闭软键盘
  * @param editText
  * @param context
  */
 public static void closeKeybord(EditText editText, Context context) {
  InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
  imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
 }
 /**
  * 判断软键盘是否显示
  * @param activity
  * @return
  */
 public static boolean isSoftShowing(Activity activity) {
  //获取当前屏幕内容的高度
  int screenHeight = activity.getWindow().getDecorView().getHeight();
  //获取View可见区域的bottom
  Rect rect = new Rect();
  //DecorView即为activity的顶级view
  activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
  //考虑到虚拟导航栏的情况(虚拟导航栏情况下:screenHeight = rect.bottom + 虚拟导航栏高度)
  //选取screenHeight*2/3进行判断
  return screenHeight*2/3 > rect.bottom;
 }
 
 public static void hintKeyboard(Activity activity) {
  InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
  if (imm.isActive() && activity.getCurrentFocus() != null) {
   if (activity.getCurrentFocus().getWindowToken() != null) {
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
   }
 
  }
 }
 /**
  * 打开软键盘
  */
 public static void openKeyboard(Handler mHandler, int s, final Activity activity) {
  mHandler.postDelayed(new Runnable() {
   @Override
   public void run() {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
   }
  }, s);
 }
 
 /**
  * 点击空白处关闭软键盘
  */
 
 public static void inputClose(View view, Context context) {
  if (view instanceof EditText) {
   view.clearFocus();
  }
  try {
   InputMethodManager im = (InputMethodManager)
     context.getSystemService(Context.INPUT_METHOD_SERVICE);
   im.hideSoftInputFromWindow(view.getWindowToken(), 0);
  } catch (NullPointerException e) {
   e.printStackTrace();
  }
 }
 
}

3.存储工具类

import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
 
/**
 * @author Administrator
 *   SharedPreferences使用工具类
 */
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class SPUtils {
 private static SharedPreferences sp;
 private static SPUtils instance = new SPUtils();
 public static Context mContext;
 
 /**
  * 保存在手机里面的文件名
  */
 public static final String FILE_NAME = "maigoo";
 
 private SPUtils() {
 }
 
 /**
  * xxx改为你想保存的sp文件名称
  */
 public static SPUtils getInstance(Context context) {
  mCOntext= context;
  if (sp == null) {
   sp = context.getApplicationContext().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
  }
  return instance;
 }
 
 /**
  * 保存数据
  */
 public void put(String key, Object value) {
  if (value instanceof Integer) {
   sp.edit().putInt(key, (Integer) value).apply();
  } else if (value instanceof String) {
   sp.edit().putString(key, (String) value).apply();
  } else if (value instanceof Boolean) {
   sp.edit().putBoolean(key, (Boolean) value).apply();
  } else if (value instanceof Float) {
   sp.edit().putFloat(key, (Float) value).apply();
  } else if (value instanceof Long) {
   sp.edit().putLong(key, (Long) value).apply();
  }
 }
 
 /**
  * 2. 读取数据
  */
 public int getInt(String key, int defValue) {
  return sp.getInt(key, defValue);
 }
 
 public String getString(String key, String defValue) {
  return sp.getString(key, defValue);
 }
 
 public boolean getBoolean(String key, boolean defValue) {
  return sp.getBoolean(key, defValue);
 }
 
 /**
  * 读取数据
  *
  * @param key
  * @param defValue
  * @return
  */
 public  T get(String key, T defValue) {
  T t = null;
  if (defValue instanceof String || defValue == null) {
   String value = sp.getString(key, (String) defValue);
   t = (T) value;
  } else if (defValue instanceof Integer) {
   Integer value = sp.getInt(key, (Integer) defValue);
   t = (T) value;
  } else if (defValue instanceof Boolean) {
   Boolean value = sp.getBoolean(key, (Boolean) defValue);
   t = (T) value;
  } else if (defValue instanceof Float) {
   Float value = sp.getFloat(key, (Float) defValue);
   t = (T) value;
  }
  return t;
 }
 
 /**
  * 保存搜索记录
  *
  * @param keyword
  */
 public void save(String keyword) {
  // 获取搜索框信息
  SharedPreferences mysp = mContext.getSharedPreferences("search_history", 0);
  String old_text = mysp.getString("history", "");
  // 利用StringBuilder.append新增内容,逗号便于读取内容时用逗号拆分开
  StringBuilder builder = new StringBuilder(old_text);
  builder.append(keyword + ",");
 
  // 判断搜索内容是否已经存在于历史文件,已存在则不重复添加
  if (!old_text.contains(keyword + ",")) {
   SharedPreferences.Editor myeditor = mysp.edit();
   myeditor.putString("history", builder.toString());
   myeditor.commit();
  }
 }
 
 public String[] getHistoryList() {
  // 获取搜索记录文件内容
  SharedPreferences sp = mContext.getSharedPreferences("search_history", 0);
  String history = sp.getString("history", "");
  // 用逗号分割内容返回数组
  String[] history_arr = history.split(",");
  // 保留前50条数据
  if (history_arr.length > 50) {
   String[] newArrays = new String[50];
   System.arraycopy(history_arr, 0, newArrays, 0, 50);
  }
  return history_arr;
 }
 
 /**
  * 清除搜索记录
  */
 public void cleanHistory() {
  SharedPreferences sp = mContext.getSharedPreferences("search_history", 0);
  SharedPreferences.Editor editor = sp.edit();
  editor.clear();
  editor.commit();
 }
}

4.Activity主要功能实现

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
import kemizhibo.rhkj.com.ijkpalaydemo.search.KeyBoardUtils;
import kemizhibo.rhkj.com.ijkpalaydemo.search.RegularUtils;
import kemizhibo.rhkj.com.ijkpalaydemo.search.SPUtils;
 
public class Main2Activity extends AppCompatActivity {
 ZFlowLayout historyFl;
 EditText autoSearch;
 Button button_search;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main2);
  historyFl = findViewById(R.id.history_fl);
  autoSearch=findViewById(R.id.autoSearch);
  button_search=findViewById(R.id.button_search);
  initHistory();
  button_search.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    if (KeyBoardUtils.isSoftShowing(Main2Activity.this)) {
     KeyBoardUtils.hintKeyboard(Main2Activity.this);
    }
    String searchKey = autoSearch.getText().toString();
    if (!isNullorEmpty(searchKey)) {
     if (RegularUtils.hasEmoji(autoSearch.getText().toString())) {
      //含有非法字符串
     } else {
      //搜索
      String keyWord = autoSearch.getText().toString();
      if (!isNullorEmpty(keyWord)) {
       SPUtils.getInstance(Main2Activity.this).save(autoSearch.getText().toString());
      }
      initHistory();
     }
    } else {
     //搜索为空
    }
 
   }
  });
 
 
 }
 
 private boolean isNullorEmpty(String str) {
  return str == null || "".equals(str);
 }
 /**
  * 初始化 历史记录列表
  */
 private void initHistory() {
 
  final String[] data = SPUtils.getInstance(Main2Activity.this).getHistoryList();
  ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
  layoutParams.setMargins(10, 10, 10, 10);
 
  historyFl.removeAllViews();
  for (int i = 0; i 

5.布局文件activity_main2 adapter_search_keyword

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
 

6.ZFlowLayout

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
 
import java.util.ArrayList;
import java.util.List;
 
/*****************************
 * @Copyright(c) 2014-2018
 * @Author:dengyalan
 * @Date:2018/1/16
 * @Description:自定义搜索标签布局
 * @Version:v1.0.0
 *****************************/
 
public class ZFlowLayout extends ViewGroup {
 /**
  * 存储所有子View
  */
 private List> mAllChildViews = new ArrayList<>();
 /**
  * 每一行的高度
  */
 private List mLineHeight = new ArrayList<>();
 
 public ZFlowLayout(Context context) {
  this(context, null);
 }
 
 public ZFlowLayout(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 
 public ZFlowLayout(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  //父控件传进来的宽度和高度以及对应的测量模式
  int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
  int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
  int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
  int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
 
  //如果当前ViewGroup的宽高为wrap_content的情况
  //自己测量的宽度
  int width = 0;
  //自己测量的高度
  int height = 0;
  //记录每一行的宽度和高度
  int lineWidth = 0;
  int lineHeight = 0;
 
  //获取子view的个数
  int childCount = getChildCount();
  for (int i = 0; i  sizeWidth) {
    //对比得到最大的宽度
    width = Math.max(width, lineWidth);
    //重置lineWidth
    lineWidth = childWidth;
    //记录行高
    height += lineHeight;
    lineHeight = childHeight;
   } else {//不换行情况
    //叠加行宽
    lineWidth += childWidth;
    //得到最大行高
    lineHeight = Math.max(lineHeight, childHeight);
   }
   //处理最后一个子View的情况
   if (i == childCount - 1) {
    width = Math.max(width, lineWidth);
    height += lineHeight;
   }
  }
  //wrap_content
  setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY &#63; sizeWidth : width,
    modeHeight == MeasureSpec.EXACTLY &#63; sizeHeight : height);
 }
 
 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
  mAllChildViews.clear();
  mLineHeight.clear();
  //获取当前ViewGroup的宽度
  int width = getWidth();
 
  int lineWidth = 0;
  int lineHeight = 0;
  //记录当前行的view
  List lineViews = new ArrayList();
  int childCount = getChildCount();
  for (int i = 0; i  width) {
    //记录LineHeight
    mLineHeight.add(lineHeight);
    //记录当前行的Views
    mAllChildViews.add(lineViews);
    //重置行的宽高
    lineWidth = 0;
    lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
    //重置view的集合
    lineViews = new ArrayList();
   }
   lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
   lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
   lineViews.add(child);
  }
  //处理最后一行
  mLineHeight.add(lineHeight);
  mAllChildViews.add(lineViews);
 
  //设置子View的位置
  int left = 0;
  int top = 0;
  //获取行数
  int lineCount = mAllChildViews.size();
  for (int i = 0; i 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程笔记。

原文链接:https://blog.csdn.net/qq_39734239/article/details/100888193


推荐阅读
  • WPF之Binding初探
      初学wpf,经常被Binding搞晕,以下记录写Binding的基础。首先,盗用张图。这图形象的说明了Binding的机理。对于Binding,意思是数据绑定,基本用法是:1、 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了10分钟了解Android的事件分发相关的知识,希望对你有一定的参考价值。什么是事件分发?大家 ... [详细]
  • 字符串匹配RabinKarp算法讲解
    问题描述:Rabin-Karp的预处理时间是O(m),匹配时间O((n-m1)m)既然与朴素算法的匹配时间一样,而且还多了一些预处理时间& ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • TerraformVersionTerraformv0.9.11AffectedResource(s)Pleas ... [详细]
  • Thisissuewasoriginallyopenedbyashashicorp/terraform#5664.Itwasmigratedhe ... [详细]
author-avatar
高小原gy_941
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有