From be1dc924a7b7cce61fabe0b03ff26c780920db95 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 24 Jun 2017 12:16:44 -0700 Subject: Update searchview logic and add travis --- .../kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt | 2 + .../ca/allanwang/kau/searchview/SearchView.kt | 128 +++++++++++++++------ library/src/main/res/layout/kau_activity_kpref.xml | 1 + library/src/main/res/layout/kau_search_view.xml | 15 +-- library/src/main/res/values/colors.xml | 3 + 5 files changed, 110 insertions(+), 39 deletions(-) create mode 100644 library/src/main/res/values/colors.xml (limited to 'library') diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt index 8ec95ee..0c6b768 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt @@ -2,6 +2,7 @@ package ca.allanwang.kau.kpref import android.os.Bundle import android.support.annotation.StringRes +import android.support.constraint.ConstraintLayout import android.support.v4.widget.TextViewCompat import android.support.v7.app.AppCompatActivity import android.support.v7.widget.RecyclerView @@ -33,6 +34,7 @@ abstract class KPrefActivity : AppCompatActivity(), KPrefActivityContract { get() = recycler.adapter as FastItemAdapter val recycler: RecyclerView get() = prefHolder.currentView as RecyclerView + val container: ConstraintLayout by bindView(R.id.kau_container) val bgCanvas: RippleCanvas by bindView(R.id.kau_ripple) val toolbarCanvas: RippleCanvas by bindView(R.id.kau_toolbar_ripple) val toolbar: Toolbar by bindView(R.id.kau_toolbar) 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() + 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(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 diff --git a/library/src/main/res/layout/kau_activity_kpref.xml b/library/src/main/res/layout/kau_activity_kpref.xml index acc1f76..856f168 100644 --- a/library/src/main/res/layout/kau_activity_kpref.xml +++ b/library/src/main/res/layout/kau_activity_kpref.xml @@ -1,6 +1,7 @@ diff --git a/library/src/main/res/layout/kau_search_view.xml b/library/src/main/res/layout/kau_search_view.xml index 799d4df..72cfd02 100644 --- a/library/src/main/res/layout/kau_search_view.xml +++ b/library/src/main/res/layout/kau_search_view.xml @@ -1,13 +1,14 @@ + android:layout_height="match_parent" + android:background="@color/kau_search_full_shadow" + android:visibility="gone" /> - + android:layout_height="match_parent" + android:visibility="gone" /> + android:scaleType="center" + android:visibility="gone" /> + #80000000 + -- cgit v1.2.3