Android search with Fragments
In short, you can't. There are a couple of reasons why creating a search interface within a Fragment
is not possible.
When creating a searchable interface, you must specify a default "searchable activity" in your Android manifest. As I'm sure you know, a
Fragment
cannot exist without a parentActivity
and thus, this separation is not possible.If you already figured out #1 already, I assume you asked this question in hopes that there is some magical "hack" out there that can get the job done. However, the documentation states that,
When the user executes a search in the search dialog or widget, the
system starts your searchable activity and delivers it the search
query in an Intent with the ACTION_SEARCH action. Your searchable
activity retrieves the query from the intent's QUERY extra, then
searches your data and presents the results.The underlying, internal system that is responsible for providing search results expects an
Activity
, not aFragment
; thus, implementing a search interface that is completely independent of anActivity
is not possible, as it would require changes to the underlying system itself. Check out the source code for theSearchableInfo
class if you don't believe me :).
That being said, it doesn't seem like it would be too difficult to achieve something similar to what you are describing. For instance, you might consider implementing your searchable-Activity so that it will accept the android.intent.action.SEARCH
intent and (instead of immediately displaying the results in a ListView
, for example) will pass the search query to your Fragment
s. For instance, consider the following searchable Activity:
public class SearchableActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
/**
* Performs a search and passes the results to the container
* Activity that holds your Fragments.
*/
public void doMySearch(String query) {
// TODO: implement this
}
}
When a search-request is made, the system will launch your searchable activity, perform the query, and will pass the results to some container Activity (based on your implementation of doMySearch
). The container Activity will then pass these results to the contained searchable Fragment
, in which the results will be displayed. The implementation requires a bit more work than what you were probably hoping for, but I'm sure there are ways that you can make it more modular, and it seems like this might be the best that you can do.
p.s. If you use this approach, you might have to pay special attention to which Activitys are added/removed to the backstack. See this post for some more information on how this might be done.
p.p.s. You might also forget about the standard search interface completely and just implement a simple search within a Fragment
as described in Raghav's post below.
SearchView implementation inside a particular Fragment
To achieve fragment
specific option menu
besides activity
's option menu
you have to implement option menu
in your fragment
too.
Activity:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_menu, menu);
return super.onCreateOptionsMenu(menu);
}
Fragment:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true); // It's important here
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
But there is a problem to order your menu
item in the toolbar
. You can specify the position of menu
item in the toolbar using android:orderInCategory
.
activity_menu:
<item
android:id="@+id/action_menu1"
android:title="Menu1"
android:orderInCategory="2"
app:showAsAction="always" />
fragment_menu:
<item
android:id="@+id/action_search"
android:title="Search"
android:orderInCategory="1"
app:showAsAction="always"
app:actionViewClass="androidx.appcompat.widget.SearchView" />
Output:
Adding SearchView in Fragment
Change your MenuSearch.xml to
<?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/action_search"
android:title="@string/app_name"
android:icon="@drawable/ic_action_search"
app:showAsAction="collapseActionView|ifRoom"
/>
</menu>
And in your fragment, add searchView.setOnQueryTextListener
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.search_option_menu, menu);
MenuItem item = menu.findItem(R.id.action_search);
SearchView searchView = new SearchView(((MainActivity) mContext).getSupportActionBar().getThemedContext());
// MenuItemCompat.setShowAsAction(item, //MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | //MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
// MenuItemCompat.setActionView(item, searchView);
// These lines are deprecated in API 26 use instead
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM);
item.setActionView(searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
searchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
}
);
}
Search Bar for a seperate fragment
Inside your fragment's onCreate()/onCreateView()
call setHasOptionsMenu(true);
This will allow your fragment to show the menu items you inflate inside the fragment's onCreateOptionsMenu()
; otherwise it uses the host Activity's menu.
Use the SearchView widget in ActionBar and a fragment
Adding this in the onCreateView function solved the issue:
(activity as AppCompatActivity).setSupportActionBar(binding.toolbar)
I am using Searchview in Fragment and my data is not added in my New array Using Kotlin
You should check if user's input text is not empty, update data of your adapter and then call notifyDataSetChanged to refresh your list.
change your first if scope to this:
if (text!!.isNotEmpty()) {
makeText(activity as Context, "working", Toast.LENGTH_LONG).show()
value.forEach {
temp.add(it) //by this line data shoul add but not added
}
recyclerView.adapter?.clear()
recyclerView.adapter?.addAll(temp)
recyclerView.adapter?.notifyDataSetChanged()
}
Related Topics
Return a Value from Asynctask in Android
How to Create a Bks (Bouncycastle) Format Java Keystore That Contains a Client Certificate Chain
How to View/Change Socket Connection Timeout on Linux
Get Domain Name from Given Url
Hibernate 5 :- Org.Hibernate.Mappingexception: Unknown Entity
How to Return 2 Values from a Java Method
Load Chrome Profile Using Selenium Webdriver Using Java
Why Does Java Implicitly (Without Cast) Convert a 'Long' to a 'Float'
Transitive Dependencies Not Resolved for Aar Library Using Gradle
Error: Unable to Run Mksdcard Sdk Tool
How to Close Rmiregistry Running on Particular Port
Java.Lang.Classnotfoundexception in Spite of Using Classpath Environment Variable
Is There a Common Java Utility to Break a List into Batches
How to Run Certain Task Every Day at a Particular Time Using Scheduledexecutorservice