aboutsummaryrefslogtreecommitdiff
path: root/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
diff options
context:
space:
mode:
Diffstat (limited to 'library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt')
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt128
1 files changed, 96 insertions, 32 deletions
diff --git a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
index d786e13..45274b8 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
@@ -3,12 +3,15 @@ package ca.allanwang.kau.searchview
import android.content.Context
import android.support.annotation.ColorInt
import android.support.annotation.IdRes
+import android.support.v7.widget.AppCompatEditText
import android.support.v7.widget.CardView
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.util.AttributeSet
import android.view.Menu
+import android.view.MenuItem
import android.view.View
+import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.ProgressBar
@@ -25,49 +28,73 @@ class SearchView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
- //configs
- var foregroundColor: Int = 0xddffffff.toInt()
- set(value) {
- if (field == value) return
- field = value
- tintForeground(value)
- }
- var navIcon: IIcon? = GoogleMaterial.Icon.gmd_arrow_back
- set(value) {
- field = value
- iconNav.setIcon(value)
- if (value == null) iconNav.gone()
- }
- var micIcon: IIcon? = GoogleMaterial.Icon.gmd_mic
- set(value) {
- field = value
- iconMic.setIcon(value)
- if (value == null) iconMic.gone()
- }
- var clearIcon: IIcon? = GoogleMaterial.Icon.gmd_clear
- set(value) {
- field = value
- iconClear.setIcon(value)
- if (value == null) iconClear.gone()
+ companion object {
+ fun bind(parent: ViewGroup, menu: Menu, @IdRes id: Int, config: Configs.() -> Unit = {}) {
+ SearchView(parent.context).apply {
+ layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
+ parent.addView(this)
+ this.bind(parent, menu, id, config)
+ }
}
+ }
+ //configs
+ inner class Configs {
+ var foregroundColor: Int = 0xddffffff.toInt()
+ set(value) {
+ if (field == value) return
+ field = value
+ tintForeground(value)
+ }
+ var navIcon: IIcon? = GoogleMaterial.Icon.gmd_arrow_back
+ set(value) {
+ field = value
+ iconNav.setIcon(value)
+ if (value == null) iconNav.gone()
+ }
+ var micIcon: IIcon? = GoogleMaterial.Icon.gmd_mic
+ set(value) {
+ field = value
+ iconMic.setIcon(value)
+ if (value == null) iconMic.gone()
+ }
+ var clearIcon: IIcon? = GoogleMaterial.Icon.gmd_clear
+ set(value) {
+ field = value
+ iconClear.setIcon(value)
+ if (value == null) iconClear.gone()
+ }
+ var revealDuration: Long = 700L
+ var shouldClearOnOpen: Boolean = true
+ var openListener: (() -> Unit)? = null
+ var closeListener: (() -> Unit)? = null
+ }
+
+ val configs = Configs()
//views
private val shadow: View by bindView(R.id.search_shadow)
- private val card: CardView by bindView(R.id.search_shadow)
+ private val card: CardView by bindView(R.id.search_cardview)
private val iconNav: ImageView by bindView(R.id.search_nav)
- //TODO edittext
+ private val editText: AppCompatEditText by bindView(R.id.search_edit_text)
private val progress: ProgressBar by bindView(R.id.search_progress)
private val iconMic: ImageView by bindView(R.id.search_mic)
private val iconClear: ImageView by bindView(R.id.search_clear)
private val recycler: RecyclerView by bindView(R.id.search_recycler)
private val adapter = FastItemAdapter<SearchItem>()
+ private lateinit var parent: ViewGroup
+ val isOpen: Boolean
+ get() = card.isVisible()
+
+ //menu view
+ private var revealX: Int = -1
+ private var revealY: Int = -1
init {
View.inflate(context, R.layout.kau_search_view, this)
- iconNav.setIcon(navIcon)
- iconMic.setIcon(micIcon)
- iconClear.setIcon(clearIcon)
- tintForeground(foregroundColor)
+ iconNav.setIcon(configs.navIcon)
+ iconMic.setIcon(configs.micIcon)
+ iconClear.setIcon(configs.clearIcon)
+ tintForeground(configs.foregroundColor)
with(recycler) {
layoutManager = LinearLayoutManager(context)
addOnScrollListener(object : RecyclerView.OnScrollListener() {
@@ -80,12 +107,26 @@ class SearchView @JvmOverloads constructor(
}
}
- fun config(action: SearchView.() -> Unit) = action()
+ fun config(config: Configs.() -> Unit) {
+ configs.config()
+ }
- fun bind(menu: Menu, @IdRes id: Int) {
+ fun bind(parent: ViewGroup, menu: Menu, @IdRes id: Int, config: Configs.() -> Unit = {}) {
+ config(config)
+ this.parent = parent
val item = menu.findItem(id)
if (item.icon == null) item.icon = GoogleMaterial.Icon.gmd_search.toDrawable(context, 20)
gone()
+ item.setOnMenuItemClickListener { getMenuItemCoords(it); revealOpen(); true }
+ shadow.setOnClickListener { revealClose() }
+ }
+
+ fun getMenuItemCoords(item: MenuItem) {
+ val view = parent.findViewById<View>(item.itemId) ?: return
+ val locations = IntArray(2)
+ view.getLocationOnScreen(locations)
+ revealX = locations[0]
+ revealY = locations[1]
}
fun tintForeground(@ColorInt color: Int) {
@@ -94,4 +135,27 @@ class SearchView @JvmOverloads constructor(
iconClear.drawable.setTint(color)
SearchItem.foregroundColor = color
}
+
+ fun revealOpen() {
+ if (isOpen) return
+ card.circularReveal(revealX, revealY, duration = configs.revealDuration,
+ onStart = {
+ configs.openListener?.invoke()
+ if (configs.shouldClearOnOpen) editText.text.clear()
+ },
+ onFinish = {
+ editText.requestFocus()
+ shadow.fadeIn()
+ })
+ }
+
+ fun revealClose() {
+ if (!isOpen) return
+ shadow.fadeOut() {
+ card.circularHide(revealX, revealY, duration = configs.revealDuration,
+ onFinish = {
+ configs.closeListener?.invoke()
+ })
+ }
+ }
} \ No newline at end of file