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
Related
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;
}
I want to add a custom view to my MainActivity Toolbar.
So i create the layout.xml file with the view inside and i add it to the main_menu.xml but i can never take it from the onPrepareOptionsMenu on my Activity.
main_menu.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">
<item
android:id="#+id/contact_search"
android:icon="#drawable/ic_search"
android:title="Search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="androidx.appcompat.widget.SearchView" />
<item
android:id="#+id/currentServerViewItem"
android:title="My account"
app:actionLayout="#layout/main_toolbar_views"
app:showAsAction="always"/>
<item
android:id="#+id/action_aboutus"
android:orderInCategory="100"
android:title="About us"
app:showAsAction="never" />
</menu>
main_toolbar_views.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="32dp"
android:layout_height="32dp">
<TextView
android:id="#+id/currentServerTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/circle_white"
android:gravity="center"
android:padding="4dp"
android:text="UU"
android:textColor="#color/colorWhite"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
private var currentServerTextView: TextView? = null
....
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
searchView = menu?.findItem(R.id.contact_search)?.actionView as SearchView
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
newText?.let {
mainViewModel.setSearchable(it)
}
return true
}
})
return super.onCreateOptionsMenu(menu)
}
.....
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
// Here i get a nullPointer exception
val menuItem = menu?.findItem(R.id.currentServerViewItem)?.actionView as ConstraintLayout
currentServerTextView = menuItem.findViewById(R.id.currentServerTextView) as TextView
currentServerTextView?.setOnClickListener {
toast("Text Clicked!!!")
}
return super.onPrepareOptionsMenu(menu)
}
When trying to debug the menuItem i get a nullPointerException although the menu is not null.
Also in the toolbar instead of the TextView layout (which is a circle textView) i see the MyAccount title only.
Why is that happening?
The issue fixed. The problem was that i had to set the xml
app:showAsAction="ifRoom"
android:orderInCategory="100"
I have created a menu icon on action bar. When it is clicked, I expect it will show something like this
But it display on the left hand side instead.
What could be this issue ?
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
inflater!!.inflate(R.menu.fragment_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.getItemId()
if (id == R.id.more) {
var popup: PopupMenu? = PopupMenu(context!!, view!!)
popup?.menuInflater?.inflate(R.menu.pop_up_menu, popup.menu)
popup?.show()
popup?.setOnMenuItemClickListener({ item: MenuItem? ->
when (item!!.itemId) {
R.id.logOut -> {
}
}
true
})
} else
super.onOptionsItemSelected(item)
return true
}
fragment_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">
<item android:id="#+id/more"
android:title="menu"
app:showAsAction="always"
android:icon="#drawable/ic_more"/>
</menu>
pop_up_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">
<item
android:id="#+id/logOut"
app:showAsAction="always"
android:title="Log Out"
/>
</menu>
The view I passing is this
#Nullable
public View getView() {
return this.mView;
}
You are passing the wrong view as what #CodeRed mentioned.
Replace
var popup: PopupMenu? = PopupMenu(context!!, view!!)
to
val vItem = getActivity().findViewById<View>(R.id.more)
var popup: PopupMenu? = PopupMenu(context!!, vItem)
Menu in ActionBar is populated automatically by system, you don't need to write code to populate it.
To achieve the menu like figure 1, fragment_menu should be like:
<menu>
<item android:title="Search" />
<item android:title="Locate" />
<item android:title="Refresh" />
<item android:title="Help" />
<item android:title="Check for update" />
</menu>
onOptionItemSelected is used to handle when above menu is clicked, not used to show the menu.
popup menu is free position menu like right click menus in windows, not the one you expect in figure 1.
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" />
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!