package com.example.expand_button
|
|
import android.animation.ValueAnimator
|
import android.content.Context
|
import android.graphics.drawable.Drawable
|
import android.util.AttributeSet
|
import android.view.LayoutInflater
|
import android.view.View
|
import android.widget.EditText
|
import android.widget.ImageView
|
import android.widget.RelativeLayout
|
import android.widget.TextView
|
import androidx.core.content.ContextCompat
|
|
class CustomSearchBar @JvmOverloads constructor(
|
context: Context,
|
attrs: AttributeSet? = null,
|
defStyleAttr: Int = 0
|
) : RelativeLayout(context, attrs, defStyleAttr) {
|
|
private var isExpanded = false
|
private var searchIcon: ImageView
|
private var searchInput: EditText
|
private var searchButton: TextView
|
private var onSearchClickListener: ((String) -> Unit)? = null
|
private var expandedWidth = 0
|
private var animationDuration: Long = 300
|
private var initialWidth = 0
|
|
init {
|
// 创建一个新的LayoutInflater,避免使用带背景的布局
|
val inflater = LayoutInflater.from(context).cloneInContext(context)
|
val root = inflater.inflate(R.layout.layout_search_bar, this, false)
|
// 清除布局文件中的背景
|
root.background = null
|
// 添加布局
|
addView(root)
|
|
// 初始化视图
|
searchIcon = findViewById(R.id.iv_search)
|
searchInput = findViewById(R.id.et_search)
|
searchButton = findViewById(R.id.tv_search)
|
|
// 设置初始状态
|
post {
|
// 保存初始宽度
|
initialWidth = width
|
|
// 确保搜索图标居中显示
|
(searchIcon.layoutParams as RelativeLayout.LayoutParams).apply {
|
removeRule(ALIGN_PARENT_START)
|
addRule(CENTER_IN_PARENT)
|
setMargins(0, 0, 0, 0)
|
}
|
|
// 初始状态隐藏输入框和搜索按钮
|
searchInput.visibility = View.GONE
|
searchButton.visibility = View.GONE
|
}
|
|
// 设置点击监听
|
searchIcon.setOnClickListener {
|
if (!isExpanded) {
|
expand()
|
}
|
}
|
|
searchButton.setOnClickListener {
|
onSearchClickListener?.invoke(searchInput.text.toString())
|
collapse()
|
}
|
|
// 设置整个布局的点击监听
|
setOnClickListener {
|
if (!isExpanded) {
|
expand()
|
}
|
}
|
}
|
|
private fun expand() {
|
if (isExpanded) return
|
|
// 计算展开后的宽度(屏幕宽度减去左右边距)
|
if (expandedWidth == 0) {
|
expandedWidth = context.resources.displayMetrics.widthPixels -
|
(32 * context.resources.displayMetrics.density).toInt()
|
}
|
|
// 创建宽度动画
|
ValueAnimator.ofInt(initialWidth, expandedWidth).apply {
|
duration = animationDuration
|
addUpdateListener { animator ->
|
layoutParams = layoutParams.apply {
|
width = animator.animatedValue as Int
|
}
|
}
|
start()
|
}
|
|
// 重置搜索图标位置
|
(searchIcon.layoutParams as RelativeLayout.LayoutParams).apply {
|
removeRule(CENTER_VERTICAL)
|
addRule(ALIGN_PARENT_START)
|
setMargins(
|
(8 * context.resources.displayMetrics.density).toInt(),
|
0,
|
0,
|
0
|
)
|
}
|
|
// 显示输入框和搜索按钮
|
searchInput.visibility = View.VISIBLE
|
searchButton.visibility = View.VISIBLE
|
searchInput.requestFocus()
|
|
isExpanded = true
|
}
|
|
private fun collapse() {
|
if (!isExpanded) return
|
|
// 创建宽度动画
|
ValueAnimator.ofInt(expandedWidth, initialWidth).apply {
|
duration = animationDuration
|
addUpdateListener { animator ->
|
layoutParams = layoutParams.apply {
|
width = animator.animatedValue as Int
|
}
|
}
|
start()
|
}
|
|
// 重置搜索图标到中心位置
|
(searchIcon.layoutParams as RelativeLayout.LayoutParams).apply {
|
removeRule(ALIGN_PARENT_START)
|
addRule(CENTER_IN_PARENT)
|
setMargins(0, 0, 0, 0)
|
}
|
|
// 隐藏输入框和搜索按钮
|
searchInput.visibility = View.GONE
|
searchButton.visibility = View.GONE
|
searchInput.setText("")
|
|
isExpanded = false
|
}
|
|
/**
|
* 设置搜索按钮点击监听器
|
* @param listener 回调函数,参数为输入框中的文本内容
|
*/
|
fun setOnSearchClickListener(listener: (String) -> Unit) {
|
onSearchClickListener = listener
|
}
|
|
/**
|
* 设置动画时长
|
*/
|
fun setAnimationDuration(duration: Long) {
|
animationDuration = duration
|
}
|
|
/**
|
* 设置提示文字
|
*/
|
fun setHint(hint: String) {
|
searchInput.hint = hint
|
}
|
|
/**
|
* 获取输入的文本
|
*/
|
fun getText(): String {
|
return searchInput.text.toString()
|
}
|
}
|