How to properly retrieve data from SearchView in Kotlin? - android

I'm working on a personal project where I want to use a searchbar.
I've been checking other post for my problem but I still don't understand what's going on.
I know that "searchView" is not referenced, but I don't know what to put instead...
Every time I use "searchView", android studio tells me : "Unsolved References"
//retrieve search query
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
val searchItem = menu.findItem(R.id.app_bar_search)
searchView = searchItem.actionView as SearchView
searchView.setQueryHint("Search View Hint")
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String): Boolean {
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
// task HERE
//on submit send entire query
return false
}
})
return true
}
Here is my menu xml:
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/app_bar_search"
android:icon="#drawable/ic_search_black_24dp"
android:title="Search"
app:showAsAction="always"
app:actionViewClass="android.widget.SearchView"/>
</menu>
And here the toolbar xml:
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbarHome"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
Feel free to ask me anything.

You need to define your searchView as a val: val searchView = searchItem.actionView as SearchView. I removed the default Toolbar in the style.xml to use yours (see onCreate method).
With this code I can compile and type some text in the searchbar.
Activity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbarHome)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
val searchItem = menu.findItem(R.id.app_bar_search)
val searchView = searchItem.actionView as SearchView
searchView.queryHint = "Search View Hint"
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String): Boolean {
return false
}
override fun onQueryTextSubmit(query: String): Boolean {
// task HERE
//on submit send entire query
return false
}
})
return true
}
my_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/app_bar_search"
android:title="Search"
app:showAsAction="always"
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
</menu>
toolbar
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbarHome"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
style.xml
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="windowActionBar">false</item>
</style>
</resources>

Related

Can't show/hide menu items on Kotlin - Android Studio

my application has a menu of 3 options, and what I want is that according to a condition that I define, it shows only 2 options, or it shows 3.
I have tried all the options that I have found on google and here, but none have worked for me.
My idea is that as soon as the view is created, the menu already shows the options that it can show according to the condition. But as I have been able to achieve it, I added a button to simulate the event.
I would greatly appreciate your help.
Here I attach the code:
1) activity_home.xml (some part)
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:onClick="ActivarMenus"/>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:menu="#menu/home_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
2) Aqui el archivo home_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_item"
android:icon="#drawable/ic_baseline_more_vert_24"
app:showAsAction="ifRoom"
tools:ignore="MenuTitle">
<menu>
<item
android:id="#+id/newRegister"
android:icon="#drawable/ic_baseline_add_24"
app:showAsAction="always"
android:visible="true"
android:title="Nueva Orden Swab" />
<item
android:id="#+id/newAnexoo"
android:icon="#drawable/ic_baseline_add_24"
app:showAsAction="always"
android:visible="true"
android:title="Nuevo Formulario Anexo O" />
<item
android:id="#+id/sync"
android:icon="#drawable/ic_baseline_sync_24"
app:showAsAction="always"
android:visible="true"
android:title="Sincronizar" />
</menu>
</item>
</menu>
3) And a part of the HomeActivity.kt
class HomeActivity : ActivityViewBinding<ActivityHomeBinding, HomeVM>() {
private var mainMenu: Menu? = null
private lateinit var spm : SharedPreferencesManager
private val adapter: OrderAdapter by inject()
override fun inflateLayout(layoutInflater: LayoutInflater) =
ActivityHomeBinding.inflate(layoutInflater)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
//MenuMain.findItem(R.id.newAnexoo).isVisible = true
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.home_menu, menu)
mainMenu = menu;
return true
}
fun ActivarMenus(view: View) {
mainMenu?.findItem(R.id.newRegister)?.isVisible = true
}
You should try this one it might be work.
if you want to change Menu Items at Run time You can use onPrepareOptionsMenu
#Override
public boolean onPrepareOptionsMenu(Menu menu){
if (//Your condition) {
menu.findItem(R.id.newRegister).setVisible(true);
}else {
menu.findItem(R.id.newRegister).setVisible(false);
}
return true;
}

ActionMode - SearchView not working (actionView is null)

I recently working on activating SearchView in ActionMode when user click on Search in onOptionsItemSelected.
However, I cant get access to the SearchView as after debugging, its actionView apparently to be null. Can anyone help me with this?
override fun onOptionsItemSelected(item: MenuItem): Boolean {
R.id.chat_search -> {
if (searchActionMode == null) {
searchActionMode = startActionMode(searchActionModeCallBack)
}
}
ActionModeCallBack
private val searchActionModeCallBack = object: ActionMode.Callback {
private lateinit var mSearchView: SearchView
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_search_message, menu)
moreMenuBtn.isVisible = false
layout_chatbox.hide()
return true
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
val searchItem = menu?.findItem(R.id.search_item_btn)
if(searchItem?.actionView != null) { <---- this seachview.actionView keeps return null
mSearchView = searchItem.actionView as SearchView
mSearchView.isIconified = false
mSearchView.onQueryTextChanged { newText ->
}
}
return true
}
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
when(item?.itemId) {
R.id.search_item_up -> {
"UP".showToast(this#ChatActivity)
}
R.id.search_item_down -> {
"DOWN".showToast(this#ChatActivity)
}
R.id.search_item_btn -> {
"SEARCH".showToast(this#ChatActivity) <-- when click on "Search" Button, "Search" is toasted.
}
}
return false
}
override fun onDestroyActionMode(mode: ActionMode?) {
searchActionMode = null
moreMenuBtn.isVisible = true
layout_chatbox.show()
}
}
menu_search_message.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/search_item_btn"
android:icon="#drawable/ic_baseline_search_24"
app:showAsAction="always"
android:title="#string/search"
app:actionViewClass="androidx.appcompat.widget.SearchView" />
<item
android:id="#+id/search_item_up"
android:icon="#drawable/ic_baseline_arrow_drop_up_24"
app:showAsAction="always"
android:title="#string/up"/>
<item
android:id="#+id/search_item_down"
android:icon="#drawable/ic_baseline_arrow_drop_down_24"
app:showAsAction="always"
android:title="#string/down"/>
</group>
</menu>
I used androidx.appcompat.widget.SearchView for all of the SearchView I used. But still I had no idea why I can't access to the SearchView in ActionMode. Please give me some help.
I faced the same issue before, and what worked for me is to set the ActionView programmatically, not in menu xml.
To do that:
First: Remove the Action ViewClass from your menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/search_item_btn"
android:icon="#drawable/ic_baseline_search_24"
app:showAsAction="always"
android:title="#string/search"/>
...
Second: Create an instance of a SearchView
Third: Inflate the menu item that you want to set its actionViewClass, and use setActionView(view) to set your instantiated SearchView.
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_search_message, menu)
moreMenuBtn.isVisible = false
layout_chatbox.hide()
// Step 2:
val searchView = SearchView(this)
searchView.setQuery(null, true)
searchView.queryHint = "Search"
// Step 3:
val searchItem = menu?.findItem(R.id.search_item_btn)
searchItem.setActionView(searchView)
return true
}
I had a workaround for this.
In my case, I will add a customview to the actionMode's title.
Here is my solution.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
R.id.chat_search -> {
if (searchActionMode == null) {
searchActionMode = startActionMode(searchActionModeCallBack)
val view = layoutInflater.inflate(R.layout.custom_searchview, null)
searchActionMode?.customView = view <-- ADD YOUR CUSTOM VIEW
val etSearch = view.findViewById<EditText>(R.id.et_search)
etSearch.requestFocus()
etSearch.doOnTextChanged { text, start, before, count ->
// TODO - handle the search query here
}
}
}
custom_searchview.xml (Just a simple EditText)
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" >
<EditText
android:id="#+id/et_search"
android:layout_alignParentStart="true"
android:maxLines="1"
android:ellipsize="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null"
android:padding="10dp"
android:layout_marginEnd="50dp"
android:hint="Search..."
android:textColorHint="#color/colorWhite"
android:textColor="#color/colorWhite"/>
</RelativeLayout>
menu_search_message.xml (REMOVE THE SEARCH VIEW ITEM)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- <item--> <-- remove the searchView from xml
<!-- android:id="#+id/search_item_btn"-->
<!-- android:icon="#drawable/ic_baseline_search_24"-->
<!-- android:title="#string/search"-->
<!-- android:enabled="true"-->
<!-- android:actionLayout="#layout/custom_searchview"-->
<!-- app:showAsAction="collapseActionView|always" />-->
<item
android:id="#+id/search_item_up"
android:icon="#drawable/ic_baseline_arrow_drop_up_24"
android:orderInCategory="2"
android:title="#string/up"
app:showAsAction="always" />
<item
android:id="#+id/search_item_down"
android:icon="#drawable/ic_baseline_arrow_drop_down_24"
android:orderInCategory="3"
android:title="#string/down"
app:showAsAction="always" />
</menu>
Final output will be like this

How to make custom toolbar menu visible for my android app?

I have prepared the custom toolbar toolbar.xml file as below:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:layout="http://schemas.android.com/tools"
android:id="#+id/my_toolbar1"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#BCBCDD"
android:elevation="4dp"
app:logo="#drawable/ic_baseline_menu_24"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
</androidx.appcompat.widget.Toolbar>
Now I have created a menu directory, and in that toolbar_menu.xml file as below:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_share"
android:title="Share"/>
<item
android:id="#+id/menu_settings"
app:showAsAction="always"
android:icon="#drawable/ic_baseline_settings_24"
android:title="Settings"/>
<item
android:id="#+id/menu_exit"
android:title="Exit"/>
</menu>
Now I have included this toolbar layout in my main activity. xml with <include/> tag.
After all this implementation I have set the toolbar in MainActivity.kt which is as below:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(my_toolbar.findViewById(R.id.my_toolbar1)) //Set the Action Bar -> toolbar
val apiService : ApiService = ApiClient.getClient()
coronaRepository =
CoronaDetailsRepository(
apiService
)
viewModel = getViewModel(1,1)
viewModel.coronaDetails.observe(this, Observer {
bindUI(it)
})
viewModel.networkState.observe(this, Observer {
loader.visibility = if (it == NetworkState.LOADING) View.VISIBLE else View.GONE
})
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.toolbar_menu, menu) // Used Menu Inflater to inflate the layout
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.menu_share -> Toast.makeText(applicationContext, "Share", Toast.LENGTH_SHORT).show()
R.id.menu_settings -> Toast.makeText(applicationContext, "Settings", Toast.LENGTH_SHORT).show()
R.id.menu_exit -> Toast.makeText(applicationContext, "Exit", Toast.LENGTH_SHORT).show()
}
return super.onOptionsItemSelected(item)
}
My toolbar is appearing on the main screen when app runs but the menu is not visible. I am wondering that what is wrong going on in my code??
Inside onCreate
..
setSupportActionBar(findViewById(R.id.my_toolbar1))
..
Inside onCreateOptionsMenu
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_toolbar, menu)
return super.onCreateOptionsMenu(menu)
}

Kotlin Android search menu item focused when activity start

Question: How to make the search menu item focused when activity start?
I would like the activity started as 2nd image as below.
Here with my code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search_qpon)
setSupportActionBar(qponSearch_toolbar)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu to use in the action bar
menuInflater.inflate(R.menu.search_menu, menu)
val searchItem = menu.findItem(R.id.app_bar_search)
if (searchItem!=null) {
val searchView = searchItem.actionView as SearchView
val searchHint = getString(R.string.searchHint)
searchView.setQueryHint(searchHint)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
if (newText!!.toString().isNotEmpty()) {
startRecyclerView(generateData(newText))
companyList.clear()
}
else {
startRecyclerView(generateData(newText))
companyList.clear()
}
return false
}
})
}
return super.onCreateOptionsMenu(menu)
}
Here with the xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#mipmap/bg"
android:orientation="vertical"
tools:context=".SearchQponActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/qponSearch_toolbar"
android:layout_width="match_parent"
app:title=""
android:layout_height="56dp"
android:background="#color/white50"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/qponSearch_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Here with the MENU file:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<item
android:id="#+id/app_bar_search"
android:icon="#android:drawable/ic_menu_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
</menu>
1st image, this is what it shows now when the activity started:
2nd image, then I click the search button, it shows:
You have to call expandActionView() method of searchItem within onCreateOptionsMenu() method. Check the code given below:
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.test_menu, menu)
val searchItem = menu?.findItem(R.id.app_bar_search)
searchItem?.expandActionView() // This line will expand the search view.
....
}
Also, you have to make a change in your menu layout XML file. You have to change the property of showAsAction from always to ifRoom|collapseActionView. Check the code given below.
<item
android:id="#+id/app_bar_search"
android:icon="#android:drawable/ic_menu_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />

Custom suggestions in SearchView in menu

I have a searchview in my menu (toolbar). It performs a search query in my recycler view and it works fine. I need to add a custom search suggestions to my searchview and I can't find any way to add it to a default searchview menu item. I have shared the code of my menu items and search query.
Menu XML file:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/actionSearch"
android:title=""
android:icon="#drawable/ic_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
<item
android:id="#+id/actionAdd"
android:title=""
android:icon="#drawable/ic_add"
app:showAsAction="always|collapseActionView"/>
<item
android:id="#+id/actionImport"
android:orderInCategory="100"
android:title="Import from phone"
app:showAsAction="never"/>
<item
android:id="#+id/actionExport"
android:orderInCategory="100"
android:title="Export as VCF"
app:showAsAction="never" />
<item
android:id="#+id/actionSettings"
android:orderInCategory="100"
android:title="Settings"
app:showAsAction="never" />
</menu>
Search Query:
private fun search(searchView: SearchView) {
searchView.queryHint = "Search Here"
searchView.setIconifiedByDefault(false)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean = false
override fun onQueryTextChange(newText: String): Boolean {
initRecentRecyclerView()
mAdapter2.getFilter().filter(newText)
recentAdapter.getFilter().filter(newText)
return true
}})
MenuItemCompat.setOnActionExpandListener(search, object : MenuItemCompat.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
initRecentRecyclerView()
return true
}
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
recentRecyclerView.visibility = View.GONE
return true
}
})
searchView.setOnFocusChangeListener({ _: View, b: Boolean ->
if(!b){
recentRecyclerView.visibility = View.GONE
}
})
searchView.setOnCloseListener{
recentRecyclerView.visibility = View.GONE
true
}
searchView.setOnQueryTextFocusChangeListener({ view: View, b: Boolean ->
if(!b){
try {
recentRecyclerView.visibility = View.GONE
}catch(e: Exception){}
}
})
}
actionSearch is the id of my searchView, searchView is the reference I have used in my kotlin code. I need to show a list of suggestions in my searchview. Hope that someone can help me out!

Categories

Resources