本文正在参加「金石计划 . 瓜分6万现金大奖」

Hello啊老铁们,今日带来一个十分有用的自定义查找框,包含了查找框、抢手查找列表、最近查找列表等常见的功用,有相似的,咱们能够直接复用,将会大大节省您的开发时间,有一点,很负责任的告知咱们,完成这个没什么技术含量,便是很简略的自定义组合View,本文除了运用介绍,我也会把详细的完成过程共享给咱们。

今日的内容大概如下:

1、作用展现

2、快速运用及特点介绍

3、详细代码完成

4、开源地址及总结

一、作用展现

作用很常见,便是往常需求中的作用,上面是查找框,下面是最近和抢手查找列表,为了方便咱们在实践需求中运用,配置了许多特点,也进行了上下控件的拆分,也便是上边查找框和下面的查找列表的拆分,能够按需进行运用。

简简单单搞一个实用的Android端搜索框

二、快速运用及特点介绍

快速运用

现在已经发布至远程Maven,咱们能够进行远程依靠运用。

1、在你的根项目下的build.gradle文件下,引进maven。

allprojects {
    repositories {
        maven { url "https://gitee.com/AbnerAndroid/almighty/raw/master" }
    }
}

2、在你需求运用的Module中build.gradle文件下,引进依靠。

dependencies {
    implementation 'com.vip:search:1.0.0'
}

详细代码

1、xml中引进SearchLayout(查找框)和SearchList(查找列表),在实践开发中,依据需求可选择运用,二者是互不相关的。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingLeft="10dp"
  android:paddingRight="10dp"
  tools:context=".MainActivity">
  <com.vip.search.SearchLayout
    android:id="@+id/search_layout"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:layout_marginTop="10dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:search_bg="@drawable/shape_stroke_10" />
  <com.vip.search.SearchList
    android:id="@+id/search_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    app:is_hot_flex_box_or_grid="true"
    app:is_visibility_history_clear="true"
    app:layout_constraintTop_toBottomOf="@id/search_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>

2、代码逻辑,以下是测验代码,如用到实践项目,请以实践项目获取控件为主。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val searchLayout = findViewById<SearchLayout>(R.id.search_layout)
        val searchList = findViewById<SearchList>(R.id.search_list)
        searchLayout.setOnTextSearchListener({
            //查找内容改动
        }, {
            //软键盘点击了查找
            searchList.doSearchContent(it)
        })
        //设置用于测验的抢手查找列表
        searchList.setHotList(getHotList())
        //抢手查找条目点击事情
        searchList.setOnHotItemClickListener { s, i ->
            Toast.makeText(this, s, Toast.LENGTH_SHORT).show()
        }
        //前史查找条目点击事情
        searchList.setOnHistoryItemClickListener { s, i ->
            Toast.makeText(this, s, Toast.LENGTH_SHORT).show()
        }
    }
    /**
* AUTHOR:AbnerMing
* INTRODUCE:模仿抢手查找列表
*/
    private val mTestHotList = arrayListOf(
        "二流小码农", "三流小可爱", "Android",
        "Kotlin", "iOS", "Java", "Python", "Php是世界上最好的语言"
    )
    private fun getHotList(): ArrayList<SearchBean> {
        return ArrayList<SearchBean>().apply {
            mTestHotList.forEachIndexed { index, s ->
                val bean = SearchBean()
                bean.content = s
                bean.isShowLeftIcon = true
                val drawable: Drawable? = if (index < 2) {
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_circle_select)
                } else if (index == 2) {
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_circle_ordinary)
                } else {
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_circle_normal)
                }
                drawable?.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
                bean.leftIcon = drawable
                add(bean)
            }
        }
    }
}

主要办法介绍

1、查找框监听

拿到searchLayout控件之后,调用setOnTextSearchListener办法即可,第一个办法是查找内容发生变化会回调,第二个办法是,点击了软键盘的查找按钮会回调,假如要在最近查找里展现,直接调用doSearchContent办法即可。

 searchLayout.setOnTextSearchListener({
            //查找内容改动
        }, {
            //软键盘点击了查找
            searchList.doSearchContent(it)
})

2、查找列表点击事情

抢手查找调用setOnHotItemClickListener办法,前史查找也便是最近查找调用setOnHistoryItemClickListener办法,都是两个参数,第一个是文本内容,第二个是索引,也便是点的是哪一个。

    	//抢手查找条目点击事情
        searchList.setOnHotItemClickListener { s, i ->
            Toast.makeText(this, s, Toast.LENGTH_SHORT).show()
        }
        //前史查找条目点击事情
        searchList.setOnHistoryItemClickListener { s, i ->
            Toast.makeText(this, s, Toast.LENGTH_SHORT).show()
        }

3、改动最近(前史)查找item布景

有的老铁说了,默许的布景我不喜欢,能否能够动态设置,必须能!

默许布景

简简单单搞一个实用的Android端搜索框

设置布景,通过setHistoryItemBg办法。

 searchList.setHistoryItemBg(R.drawable.shape_solid_d43c3c_10)

作用展现

简简单单搞一个实用的Android端搜索框

4、动态设置抢手查找热度

可能在许多需求中,需求展现几个热度,有的是依照色彩区别,如下图:

简简单单搞一个实用的Android端搜索框

完成起来很简略,在设置抢手列表(setHotList)的时分,针对传递的对象设置leftIcon即可。测验代码如下:


 private fun getHotList(): ArrayList<SearchBean> {
        return ArrayList<SearchBean>().apply {
            mTestHotList.forEachIndexed { index, s ->
                val bean = SearchBean()
                bean.content = s
                bean.isShowLeftIcon = true
                val drawable: Drawable? = if (index < 2) {
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_circle_select)
                } else if (index == 2) {
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_circle_ordinary)
                } else {
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.shape_circle_normal)
                }
                drawable?.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
                bean.leftIcon = drawable
                add(bean)
            }
        }
    }

详细的哪个数据展现什么色彩,直接设置即可,想怎样展现就怎样展现。当然了除了展现不同的热度之外,还有一些其他的变量,isShowLeftIcon为是否展现文字左面的icon,textColor为当时文字的色彩,依据不同的色彩,咱们也能够完成下面的作用。

简简单单搞一个实用的Android端搜索框

除了常见的办法之外,还供给了许多的特点操作,详细的咱们能够看下面,按需运用即可。

特点介绍

为了让功用灵活多变,也为了满意更多的需求款式,现在自定义了许多特点,咱们能够按自己的需求进行设置,或许直接去GitHub中下载源码更改也能够。

SearchLayout(查找框特点)

特点 类型 概述
search_icon reference 查找图标,可直接从drawable或许mipmap中设置
search_icon_width dimension 查找图标的宽
search_icon_height dimension 查找图标的高
search_icon_left dimension 查找图标间隔左面的间隔
search_icon_delete reference 查找删去图标,右侧的删去
search_icon_delete_width dimension 查找删去图标的宽
search_icon_delete_height dimension 查找删去图标的高
search_icon_delete_right dimension 查找删去图标间隔右边的间隔
search_hint string 查找框占位字符
search_hint_color color 查找框占位字符色彩
search_color color 查找框文字色彩
search_size dimension 查找框文字大小
search_text_cursor reference 查找框光标
search_bg reference 整个查找框布景

SearchList(查找列表特点)

特点 类型 概述
is_hot_flex_box_or_grid boolean 抢手查找列表款式,是网格还是流式布局
is_hot_center boolean 抢手查找列表款式,内容是否居中
hot_grid_span_count integer 抢手查找列表款式,假如是网格布局,条目列数,默许2
hot_item_top_margin integer 抢手查找列表 item间隔上边的间隔
hot_item_color color 抢手查找列表 item 文字色彩
hot_item_size dimension 抢手查找列表 item 文字大小
hot_item_line integer 抢手查找列表 item 文字展现几行
hot_item_bg reference 抢手查找列表 item 布景
hot_item_margin_top reference 抢手查找列表 item 间隔上边的间隔
hot_padding_left dimension 抢手查找列表 内边距,左
hot_padding_top dimension 抢手查找列表 内边距,上
hot_padding_right dimension 抢手查找列表 内边距,右
hot_padding_bottom dimension 抢手查找列表 内边距,下
is_history_flex_box_or_grid boolean 前史查找列表款式,是网格还是流式布局
history_flex_box_count integer 前史查找列表,最多展现几个item,默许10
is_history_center boolean 前史查找列表款式,内容是否居中
history_grid_span_count integer 前史查找列表款式,假如是网格布局,条目列数,默许2
history_item_top_margin integer 前史查找列表 item间隔上边的间隔
history_item_color color 前史查找列表 item 文字色彩
history_item_size dimension 前史查找列表 item 文字大小
history_item_margin_top dimension 前史查找列表 item 间隔上边的间隔
is_visibility_history_clear boolean 前史查找右边是否展现铲除小按钮
history_clear_icon reference 前史查找右边的铲除小按钮
history_clear_text string 前史查找右边的铲除文字
history_clear_size dimension 前史查找右边的铲除文字大小
history_clear_color color 前史查找右边的铲除文字色彩
history_padding_left dimension 前史查找列表 内边距,左
history_padding_top dimension 前史查找列表 内边距,上
history_padding_right dimension 前史查找列表 内边距,右
history_padding_bottom dimension 前史查找列表 内边距,下

三、详细代码完成

关于这个组合View的完成方法,我是分为了两个View,咱们在上边的运用中应该也看到了,一个是查找框SearchLayout,一个是查找框下面的查找列表展现SearchList,开头就论述了,没啥技术含量,简略的罗列下代码完成吧。

SearchLayout是一个组合View,中间是一个EditText,左右两头是一个ImageView,也便是查找图标和删去图标,如下图:

简简单单搞一个实用的Android端搜索框

SearchLayout自身没有啥要说的,无非便是把View组合到了一同,在开发的时分,既然要给他人运用,那么就要拓展出许多的动态特点或许办法出来,这是很重要的,所以,在封装的时分,自定义特点无比的重要,需求精确和仔细,这一块没啥好说的,有一点需求留意,也便是EditText绑定软键盘查找,除了设置特点android:imeOptions=”actionSearch”,也要设置,android:singleLine=”true”,方可生效。

SearchList其实也没啥好说的,也是一个组合View,运用的是上下两个RecyclerView来完成的,至于丢失布局,采用的是google供给的flexbox,设置布局管理器即可。

recyclerView.layoutManager = FlexboxLayoutManager(mContext)

除了这个之外,可能需求论述的也便是最近查找的存储机制了,存储呢,Android中供给了许多的存储方法,比方数据库,SharedPreferences,SD卡,还有DataStore,MMKV等,无论哪一种吧,选择适合的即可,这个开源中,不想引进其他的三方了,直接运用的是SharedPreferences。

详细的完成方法,把查找的内容,转成json串,以json串的方式进行存储,这儿借助了原生的JSONArray和JSONObject。流程便是,触发查找内容后,先从SharedPreferences取出之前存储的内容,放到JSONArray中,当时查找内容假如存在JSONArray中,那儿就要执行删去原来的,再把新的内容插入到第一个的位置,假如不存在JSONArray中,直接添加即可,随后再转成字符串存储即可。

当然了,一般在正常的需求开发中,最近查找列表肯定不是无限展现的,都有固定的展现个数,比方10个,比方15个,所以,当超过指定的个数,也便是指定的阀门后,就要执行删去的操作。

    	val searchHistory = getSearchHistory()
        if (!TextUtils.isEmpty(it)) {
            val jsonArray: JSONArray = if (TextUtils.isEmpty(searchHistory)) {
                JSONArray()
            } else {
                JSONArray(searchHistory)
            }
            val json = JSONObject()
            json.put("content", it)
            //假如呈现了相同的,删去后,加到第一个
            var isEqual = false
            var equalPosition = 0
            for (i in 0 until jsonArray.length()) {
                val item = jsonArray.getJSONObject(i)
                val content = item.getString("content")
                if (it == content) {
                    isEqual = true
                    equalPosition = i
                    break
                }
            }
            //有相同的
            if (isEqual) {
                jsonArray.remove(equalPosition)
            } else {
                //超过了指定的阀门之后,就不在扩大
                if (jsonArray.length() >= mHistoryListSize) {
                    jsonArray.remove(0)
                }
            }
            jsonArray.put(json)
            SearchSharedPreUtils.put(mContext!!, "search_history", jsonArray.toString())
        }
        getSearchHistory()?.let {
            eachSearchHistory(it)
        }
        //两个有一个不为空,展现
        if (!TextUtils.isEmpty(it) || !TextUtils.isEmpty(searchHistory)) {
            showOrHideHistoryLayout(View.VISIBLE)
        }

当然了,存储的逻辑,有许多的完成的方法,这儿并不是最优的,仅仅供给了一种思路,咱们能够依照自己的方法来操作。

四、开源地址及总结

开源地址:github.com/AbnerMing88…

查找列表,无论是抢手还是最近的查找列表,均支撑网格和丢失布局方式展现,咱们看特点相关介绍中即可。这个查找框自身便是很简略的作用还有代码,咱们直接看源码或文中介绍即可,就不多赘述了。