aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2018-01-02 23:38:51 -0500
committerGitHub <noreply@github.com>2018-01-02 23:38:51 -0500
commit2a9d5916a2acd0b468b9aa28977021fdd483e2aa (patch)
treea2df6258e213546a1807e15e45aa921ee69f192b
parent71f5dc2f7ce5b8183421586e6a77be65040a4dff (diff)
downloadkau-2a9d5916a2acd0b468b9aa28977021fdd483e2aa.tar.gz
kau-2a9d5916a2acd0b468b9aa28977021fdd483e2aa.tar.bz2
kau-2a9d5916a2acd0b468b9aa28977021fdd483e2aa.zip
Fix/searchview (#123)
* Use workaround for kclick * Add text cleared callback * Add bundle scene transition functions * Add applier * Remove need for explicit context * Revert
-rw-r--r--about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt11
-rw-r--r--about/src/main/res-public/values/public.xml2
-rw-r--r--adapter/src/main/res-public/values/public.xml2
-rw-r--r--android-lib.gradle5
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt26
-rw-r--r--core/src/main/res-public/values/public.xml2
-rw-r--r--docs/Changelog.md1
-rw-r--r--kpref-activity/src/main/res-public/values/public.xml2
-rw-r--r--mediapicker/src/main/res-public/values/public.xml2
-rw-r--r--sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt8
-rw-r--r--searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt56
11 files changed, 92 insertions, 25 deletions
diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt
index a5f5318..c99f7c2 100644
--- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt
+++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt
@@ -1,6 +1,6 @@
package ca.allanwang.kau.about
-import android.app.Activity
+import android.content.Context
import ca.allanwang.kau.utils.startActivity
import ca.allanwang.kau.utils.withSceneTransitionAnimation
@@ -11,8 +11,7 @@ import ca.allanwang.kau.utils.withSceneTransitionAnimation
/**
* About activity launcher
*/
-inline fun <reified T : AboutActivityBase> Activity.kauLaunchAbout() {
- startActivity<T>(bundleBuilder = {
- withSceneTransitionAnimation(this@kauLaunchAbout)
- })
-} \ No newline at end of file
+inline fun <reified T : AboutActivityBase> Context.kauLaunchAbout() =
+ startActivity<T>(bundleBuilder = {
+ withSceneTransitionAnimation(this@kauLaunchAbout)
+ }) \ No newline at end of file
diff --git a/about/src/main/res-public/values/public.xml b/about/src/main/res-public/values/public.xml
index 3739dd1..2db68c4 100644
--- a/about/src/main/res-public/values/public.xml
+++ b/about/src/main/res-public/values/public.xml
@@ -1,4 +1,4 @@
<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
- <!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
+<!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
<public name='Kau.About' type='style' />
</resources> \ No newline at end of file
diff --git a/adapter/src/main/res-public/values/public.xml b/adapter/src/main/res-public/values/public.xml
index 4d16c2a..cf14680 100644
--- a/adapter/src/main/res-public/values/public.xml
+++ b/adapter/src/main/res-public/values/public.xml
@@ -1,4 +1,4 @@
<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
- <!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
+<!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
<public name='dummy' type='id' />
</resources> \ No newline at end of file
diff --git a/android-lib.gradle b/android-lib.gradle
index c1fb523..d3651dc 100644
--- a/android-lib.gradle
+++ b/android-lib.gradle
@@ -28,11 +28,6 @@ android {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
- compileOptions {
- targetCompatibility 1.8
- sourceCompatibility 1.8
- }
-
buildTypes {
release {
minifyEnabled false
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
index 76c314a..82cd577 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
@@ -6,6 +6,8 @@ import android.app.ActivityOptions
import android.content.Context
import android.os.Bundle
import android.support.annotation.AnimRes
+import android.util.Pair
+import android.view.View
import ca.allanwang.kau.R
/**
@@ -25,7 +27,29 @@ infix fun Bundle.with(bundle: Bundle?): Bundle {
@SuppressLint("NewApi")
fun Bundle.withSceneTransitionAnimation(context: Context) {
if (context !is Activity || !buildIsLollipopAndUp) return
- this with ActivityOptions.makeSceneTransitionAnimation(context).toBundle()
+ val options = ActivityOptions.makeSceneTransitionAnimation(context)
+ putAll(options.toBundle())
+}
+
+/**
+ * Given the parent view and map of view ids to tags,
+ * create a scene transition animation
+ */
+fun Bundle.withSceneTransitionAnimation(parent: View, data: Map<Int, String>) =
+ withSceneTransitionAnimation(parent.context, data.mapKeys { (id, _) ->
+ parent.findViewById<View>(id)
+ })
+
+/**
+ * Given a mapping of views to tags,
+ * create a scene transition animation
+ */
+@SuppressLint("NewApi")
+fun Bundle.withSceneTransitionAnimation(context: Context, data: Map<View, String>) {
+ if (context !is Activity || !buildIsLollipopAndUp) return
+ val options = ActivityOptions.makeSceneTransitionAnimation(context,
+ *data.map { (view, tag) -> Pair(view, tag) }.toTypedArray())
+ putAll(options.toBundle())
}
fun Bundle.withCustomAnimation(context: Context,
diff --git a/core/src/main/res-public/values/public.xml b/core/src/main/res-public/values/public.xml
index c309a70..f831c6d 100644
--- a/core/src/main/res-public/values/public.xml
+++ b/core/src/main/res-public/values/public.xml
@@ -1,5 +1,5 @@
<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
- <!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
+<!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
<public name='kau_exit_slide_bottom' type='transition' />
<public name='kau_exit_slide_left' type='transition' />
<public name='kau_enter_slide_right' type='transition' />
diff --git a/docs/Changelog.md b/docs/Changelog.md
index e6e4488..88fe4ff 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -2,6 +2,7 @@
## v3.6.1
* :core: [Breaking] Removed private text field and introduced lazy logging functions
+* :adapter: Improve library item layout
## v3.6.0
* :adapter: Create withOnRepeatedClickListener
diff --git a/kpref-activity/src/main/res-public/values/public.xml b/kpref-activity/src/main/res-public/values/public.xml
index bd4f615..b5fb383 100644
--- a/kpref-activity/src/main/res-public/values/public.xml
+++ b/kpref-activity/src/main/res-public/values/public.xml
@@ -1,5 +1,5 @@
<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
- <!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
+<!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
<public name='kau_pref_barrier' type='id' />
<public name='kau_pref_container' type='id' />
<public name='kau_pref_desc' type='id' />
diff --git a/mediapicker/src/main/res-public/values/public.xml b/mediapicker/src/main/res-public/values/public.xml
index 41bcbfd..3c6f0fa 100644
--- a/mediapicker/src/main/res-public/values/public.xml
+++ b/mediapicker/src/main/res-public/values/public.xml
@@ -1,5 +1,5 @@
<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
- <!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
+<!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
<public name='Kau.MediaPicker' type='style' />
<public name='Kau.MediaPicker.Overlay' type='style' />
<public name='kau_blurred_image_selection_overlay' type='color' />
diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt
index 6784705..b27a713 100644
--- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt
+++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt
@@ -1,10 +1,11 @@
package ca.allanwang.kau.sample
+import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
-import ca.allanwang.kau.about.kauLaunchAbout
+import ca.allanwang.kau.about.AboutActivityBase
import ca.allanwang.kau.email.sendEmail
import ca.allanwang.kau.kpref.activity.CoreAttributeContract
import ca.allanwang.kau.kpref.activity.KPrefActivity
@@ -287,3 +288,8 @@ class MainActivity : KPrefActivity() {
}
}
}
+
+inline fun <reified T : AboutActivityBase> Context.kauLaunchAbout() =
+ startActivity<T>(bundleBuilder = {
+ withSceneTransitionAnimation(this@kauLaunchAbout)
+ }) \ No newline at end of file
diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
index 1cd811e..e3a4678 100644
--- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
+++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
@@ -52,19 +52,23 @@ class SearchView @JvmOverloads constructor(
* However, these are the main config options
*/
class Configs {
+
/**
* The foreground color accounts for all text colors and icon colors
* Various alpha levels may be used for sub texts/dividers etc
*/
var foregroundColor: Int = SearchItem.foregroundColor
+
/**
* Namely the background for the card and recycler view
*/
var backgroundColor: Int = SearchItem.backgroundColor
+
/**
* Icon for the leftmost ImageView, which typically contains the hamburger menu/back arror
*/
var navIcon: IIcon? = GoogleMaterial.Icon.gmd_arrow_back
+
/**
* Optional icon just to the left of the clear icon
* This is not implemented by default, but can be used for anything, such as mic or redirects
@@ -72,43 +76,53 @@ class SearchView @JvmOverloads constructor(
* Set the iicon as null to hide the extra icon
*/
var extraIcon: Pair<IIcon, OnClickListener>? = null
+
/**
* Icon for the rightmost ImageView, which typically contains a close icon
*/
var clearIcon: IIcon? = GoogleMaterial.Icon.gmd_clear
+
/**
* Duration for the circular reveal animation
*/
var revealDuration: Long = 300L
+
/**
* Duration for the auto transition, which is namely used to resize the recycler view
*/
var transitionDuration: Long = 100L
+
/**
* Defines whether the edit text and mainAdapter should clear themselves when the searchView is closed
*/
var shouldClearOnClose: Boolean = false
+
/**
* Callback that will be called every time the searchView opens
*/
var openListener: ((searchView: SearchView) -> Unit)? = null
+
/**
* Callback that will be called every time the searchView closes
*/
var closeListener: ((searchView: SearchView) -> Unit)? = null
+
/**
* Draw a divider between the search bar and the suggestion items
* The divider is colored based on the [foregroundColor]
*/
var withDivider: Boolean = true
+
/**
* Hint string to be set in the searchView
*/
var hintText: String? = null
+
/**
* Hint string res to be set in the searchView
*/
var hintTextRes: Int = -1
+
/**
* StringRes for a "no results found" item
* If [results] is ever set to an empty list, it will default to
@@ -118,29 +132,46 @@ class SearchView @JvmOverloads constructor(
* which you may use
*/
var noResultsFound: Int = -1
+
/**
* Callback for when the query changes
+ * This callback does not run on the ui thread!
+ * It is always on a worker thread, so there is no need for asynchronous calls
+ * Likewise, calls modifying the UI should be passed through [runOnUiThread]
*/
var textCallback: (query: String, searchView: SearchView) -> Unit = { _, _ -> }
+
+ /**
+ * Callback for when the query is changed to an empty string
+ * Typically, this may be ignored as the adapter will simply be cleared,
+ * but if we wish to do something else, we may pass a function
+ * Returns [true] if the action was consumed, [false] otherwise (to execute default behaviour)
+ */
+ var textClearedCallback: (searchView: SearchView) -> Boolean = { _ -> false }
+
/**
* Callback for when the search action key is detected from the keyboard
* Returns true if the searchbar should close afterwards, and false otherwise
*/
var searchCallback: (query: String, searchView: SearchView) -> Boolean = { _, _ -> false }
+
/**
* Debouncing interval between callbacks
*/
var textDebounceInterval: Long = 0
+
/**
* Click event for suggestion items
* This event is only triggered when [key] is not blank (like in [noResultsFound]
*/
var onItemClick: (position: Int, key: String, content: String, searchView: SearchView) -> Unit = { _, _, _, _ -> }
+
/**
* Long click event for suggestion items
* This event is only triggered when [key] is not blank (like in [noResultsFound]
*/
var onItemLongClick: (position: Int, key: String, content: String, searchView: SearchView) -> Unit = { _, _, _, _ -> }
+
/**
* If a [SearchItem]'s title contains the submitted query, make that portion bold
* See [SearchItem.withHighlights]
@@ -198,7 +229,7 @@ class SearchView @JvmOverloads constructor(
context.runOnUiThread { cardTransition(); adapter.clear() }
}
- val configs = Configs()
+ private val configs = Configs()
//views
private val shadow: View by bindView(R.id.kau_search_shadow)
private val card: BoundedCardView by bindView(R.id.kau_search_cardview)
@@ -211,11 +242,17 @@ class SearchView @JvmOverloads constructor(
private val recycler: RecyclerView by bindView(R.id.kau_search_recycler)
private var textCallback: Debouncer2<String, SearchView>
= debounce(0) { query, _ -> KL.d { "Search query $query found; set your own textCallback" } }
- val adapter = FastItemAdapter<SearchItem>()
- var menuItem: MenuItem? = null
+ private val adapter = FastItemAdapter<SearchItem>()
+ private var menuItem: MenuItem? = null
val isOpen: Boolean
get() = parent != null && card.isVisible
+ /**
+ * The current text located in our searchview
+ */
+ val query: String
+ get() = editText.text.toString().trim()
+
/*
* Ripple start points and search view offset
* These are calculated every time the search view is opened,
@@ -258,8 +295,12 @@ class SearchView @JvmOverloads constructor(
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
- if (s.isNotBlank()) textCallback(s.toString().trim(), this@SearchView)
- else clearResults()
+ val text = s.toString().trim()
+ textCallback.cancel()
+ if (text.isNotEmpty())
+ textCallback(text, this@SearchView)
+ else if (!configs.textClearedCallback(this@SearchView))
+ clearResults()
}
})
editText.setOnEditorActionListener { _, actionId, _ ->
@@ -321,12 +362,13 @@ class SearchView @JvmOverloads constructor(
menuItem = null
}
+ private val locations = IntArray(2)
+
private fun configureCoords(item: MenuItem?) {
item ?: return
if (parent !is ViewGroup) return
val view = parentViewGroup.findViewById<View>(item.itemId) ?: return
- val locations = IntArray(2)
- view.getLocationOnScreen(locations)
+ view.getLocationInWindow(locations)
menuX = (locations[0] + view.width / 2)
menuHalfHeight = view.height / 2
menuY = (locations[1] + menuHalfHeight)