Added clear button in search
This commit is contained in:
parent
778ec942a5
commit
4da1f68617
2 changed files with 198 additions and 171 deletions
|
@ -1,215 +1,225 @@
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.app.Service
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.speech.RecognizerIntent
|
import android.speech.RecognizerIntent
|
||||||
import android.text.*
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.TextView.BufferType
|
import android.widget.TextView.BufferType
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
||||||
import androidx.recyclerview.widget.*
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.transition.TransitionManager
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.*
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.retromusic.*
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
|
import code.name.monkey.retromusic.App
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
import code.name.monkey.retromusic.adapter.SearchAdapter
|
import code.name.monkey.retromusic.adapter.SearchAdapter
|
||||||
import code.name.monkey.retromusic.mvp.presenter.*
|
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
|
||||||
import code.name.monkey.retromusic.util.*
|
import code.name.monkey.retromusic.mvp.presenter.SearchView
|
||||||
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import kotlinx.android.synthetic.main.activity_search.*
|
import kotlinx.android.synthetic.main.activity_search.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView {
|
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var searchPresenter: SearchPresenter
|
lateinit var searchPresenter: SearchPresenter
|
||||||
|
|
||||||
private var searchAdapter: SearchAdapter? = null
|
private var searchAdapter: SearchAdapter? = null
|
||||||
private var query: String? = null
|
private var query: String? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
setDrawUnderStatusBar()
|
setDrawUnderStatusBar()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_search)
|
setContentView(R.layout.activity_search)
|
||||||
App.musicComponent.inject(this)
|
App.musicComponent.inject(this)
|
||||||
searchPresenter.attachView(this)
|
searchPresenter.attachView(this)
|
||||||
|
|
||||||
setStatusbarColorAuto()
|
setStatusbarColorAuto()
|
||||||
setNavigationBarColorPrimary()
|
setNavigationBarColorPrimary()
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
|
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
setUpToolBar()
|
setUpToolBar()
|
||||||
setupSearchView()
|
setupSearchView()
|
||||||
|
|
||||||
if (intent.getBooleanExtra(EXTRA_SHOW_MIC, false)) {
|
if (intent.getBooleanExtra(EXTRA_SHOW_MIC, false)) {
|
||||||
startMicSearch()
|
startMicSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
back.setOnClickListener { onBackPressed() }
|
back.setOnClickListener { onBackPressed() }
|
||||||
voiceSearch.setOnClickListener { startMicSearch() }
|
voiceSearch.setOnClickListener { startMicSearch() }
|
||||||
|
clearText.setOnClickListener { searchView.clearText() }
|
||||||
|
searchContainer.setCardBackgroundColor(RetroColorUtil.toolbarColor(this))
|
||||||
|
|
||||||
searchContainer.setCardBackgroundColor(RetroColorUtil.toolbarColor(this))
|
keyboardPopup.setOnClickListener {
|
||||||
|
val inputManager = getSystemService(Service.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
inputManager.showSoftInput(searchView, InputMethodManager.SHOW_IMPLICIT)
|
||||||
|
}
|
||||||
|
|
||||||
keyboardPopup.setOnClickListener {
|
keyboardPopup.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
||||||
val inputManager = getSystemService(Service.INPUT_METHOD_SERVICE) as InputMethodManager
|
ColorStateList.valueOf(
|
||||||
inputManager.showSoftInput(searchView, InputMethodManager.SHOW_IMPLICIT)
|
MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(ThemeStore.accentColor(this)))
|
||||||
}
|
).apply {
|
||||||
|
keyboardPopup.setTextColor(this)
|
||||||
|
keyboardPopup.iconTint = this
|
||||||
|
}
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
query = savedInstanceState.getString(QUERY);
|
||||||
|
}
|
||||||
|
|
||||||
keyboardPopup.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
}
|
||||||
ColorStateList.valueOf(
|
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
|
||||||
this,
|
|
||||||
ColorUtil.isColorLight(
|
|
||||||
ThemeStore.accentColor(
|
|
||||||
this
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
).apply {
|
|
||||||
keyboardPopup.setTextColor(this)
|
|
||||||
keyboardPopup.iconTint = this
|
|
||||||
}
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
query = savedInstanceState.getString(QUERY);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
private fun setupRecyclerView() {
|
||||||
|
searchAdapter = SearchAdapter(this, emptyList())
|
||||||
|
searchAdapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||||
|
override fun onChanged() {
|
||||||
|
super.onChanged()
|
||||||
|
empty.visibility = if (searchAdapter!!.itemCount < 1) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
recyclerView.apply {
|
||||||
|
layoutManager = LinearLayoutManager(this@SearchActivity)
|
||||||
|
adapter = searchAdapter
|
||||||
|
}
|
||||||
|
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
|
super.onScrolled(recyclerView, dx, dy)
|
||||||
|
if (dy > 0) {
|
||||||
|
keyboardPopup.shrink()
|
||||||
|
} else if (dy < 0) {
|
||||||
|
keyboardPopup.extend()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupSearchView() {
|
||||||
searchAdapter = SearchAdapter(this, emptyList())
|
searchView.addTextChangedListener(this)
|
||||||
searchAdapter!!.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
}
|
||||||
override fun onChanged() {
|
|
||||||
super.onChanged()
|
|
||||||
empty.visibility = if (searchAdapter!!.itemCount < 1) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
})
|
|
||||||
recyclerView.apply {
|
|
||||||
layoutManager = LinearLayoutManager(this@SearchActivity)
|
|
||||||
adapter = searchAdapter
|
|
||||||
}
|
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
|
||||||
if (dy > 0) {
|
|
||||||
keyboardPopup.shrink()
|
|
||||||
} else if (dy < 0) {
|
|
||||||
keyboardPopup.extend()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupSearchView() {
|
override fun onDestroy() {
|
||||||
searchView.addTextChangedListener(this)
|
super.onDestroy()
|
||||||
}
|
searchPresenter.detachView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onDestroy()
|
super.onSaveInstanceState(outState)
|
||||||
searchPresenter.detachView()
|
outState.putString(QUERY, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
private fun setUpToolBar() {
|
||||||
super.onSaveInstanceState(outState)
|
title = null
|
||||||
outState.putString(QUERY, query)
|
appBarLayout.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpToolBar() {
|
private fun search(query: String) {
|
||||||
title = null
|
this.query = query
|
||||||
appBarLayout.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
|
TransitionManager.beginDelayedTransition(appBarLayout)
|
||||||
}
|
voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
|
||||||
|
clearText.visibility = if (query.isNotEmpty()) View.VISIBLE else View.GONE
|
||||||
|
searchPresenter.search(query)
|
||||||
|
}
|
||||||
|
|
||||||
private fun search(query: String) {
|
override fun onMediaStoreChanged() {
|
||||||
this.query = query
|
super.onMediaStoreChanged()
|
||||||
voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
|
query?.let { search(it) }
|
||||||
searchPresenter.search(query)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
super.onMediaStoreChanged()
|
hideSoftKeyboard()
|
||||||
query?.let { search(it) }
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextChange(newText: String): Boolean {
|
||||||
hideSoftKeyboard()
|
search(newText)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String): Boolean {
|
private fun hideSoftKeyboard() {
|
||||||
search(newText)
|
RetroUtil.hideSoftKeyboard(this@SearchActivity)
|
||||||
return false
|
if (searchView != null) {
|
||||||
}
|
searchView.clearFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun hideSoftKeyboard() {
|
override fun showEmptyView() {
|
||||||
RetroUtil.hideSoftKeyboard(this@SearchActivity)
|
searchAdapter?.swapDataSet(ArrayList())
|
||||||
if (searchView != null) {
|
}
|
||||||
searchView.clearFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showEmptyView() {
|
override fun showData(data: MutableList<Any>) {
|
||||||
searchAdapter?.swapDataSet(ArrayList())
|
searchAdapter?.swapDataSet(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showData(data: MutableList<Any>) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
searchAdapter?.swapDataSet(data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
}
|
when (requestCode) {
|
||||||
|
REQ_CODE_SPEECH_INPUT -> {
|
||||||
|
if (resultCode == Activity.RESULT_OK && null != data) {
|
||||||
|
val result: ArrayList<String>? = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
|
||||||
|
query = result?.get(0)
|
||||||
|
searchView.setText(query, BufferType.EDITABLE)
|
||||||
|
searchPresenter.search(query!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
private fun startMicSearch() {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
||||||
when (requestCode) {
|
intent.putExtra(
|
||||||
REQ_CODE_SPEECH_INPUT -> {
|
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
|
||||||
if (resultCode == Activity.RESULT_OK && null != data) {
|
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
|
||||||
val result: ArrayList<String>? = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
|
)
|
||||||
query = result?.get(0)
|
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
|
||||||
searchView.setText(query, BufferType.EDITABLE)
|
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
|
||||||
searchPresenter.search(query!!)
|
try {
|
||||||
}
|
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT)
|
||||||
}
|
} catch (e: ActivityNotFoundException) {
|
||||||
}
|
e.printStackTrace()
|
||||||
}
|
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
private fun startMicSearch() {
|
}
|
||||||
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
|
|
||||||
intent.putExtra(
|
|
||||||
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
|
|
||||||
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
|
|
||||||
)
|
|
||||||
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
|
|
||||||
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
|
|
||||||
try {
|
|
||||||
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT)
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
}
|
||||||
|
|
||||||
}
|
override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
search(newText.toString())
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
search(newText.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) {
|
}
|
||||||
|
|
||||||
}
|
companion object {
|
||||||
|
val TAG: String = SearchActivity::class.java.simpleName
|
||||||
|
|
||||||
companion object {
|
const val EXTRA_SHOW_MIC = "extra_show_mic"
|
||||||
val TAG: String = SearchActivity::class.java.simpleName
|
const val QUERY: String = "query"
|
||||||
|
|
||||||
const val EXTRA_SHOW_MIC = "extra_show_mic"
|
private const val REQ_CODE_SPEECH_INPUT = 9002
|
||||||
const val QUERY: String = "query"
|
}
|
||||||
|
|
||||||
private const val REQ_CODE_SPEECH_INPUT = 9002
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun TextInputEditText.clearText() {
|
||||||
|
text = null
|
||||||
|
}
|
|
@ -55,16 +55,33 @@
|
||||||
<requestFocus />
|
<requestFocus />
|
||||||
</com.google.android.material.textfield.TextInputEditText>
|
</com.google.android.material.textfield.TextInputEditText>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<FrameLayout
|
||||||
android:id="@+id/voiceSearch"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0">
|
||||||
android:background="?roundSelector"
|
|
||||||
android:padding="12dp"
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
app:srcCompat="@drawable/ic_mic_white_24dp"
|
android:id="@+id/voiceSearch"
|
||||||
app:tint="?colorOnSurface"
|
android:layout_width="wrap_content"
|
||||||
tools:visibility="visible" />
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
|
android:background="?roundSelector"
|
||||||
|
android:padding="12dp"
|
||||||
|
app:srcCompat="@drawable/ic_mic_white_24dp"
|
||||||
|
app:tint="?colorOnSurface"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/clearText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?roundSelector"
|
||||||
|
android:padding="12dp"
|
||||||
|
app:srcCompat="@drawable/ic_close_white_24dp"
|
||||||
|
app:tint="?colorOnSurface"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
Loading…
Reference in a new issue