Reputation: 113
I have given SearchView in activity with custom toolbar and filter data goes to fragment. When I click on the search icon,toolbar size increasing. Navigation bar is used in that activity,may be it is issue?. It is working with separate activity without navigation bar.vb
Here is my code: Activity.xml :
<android.support.design.widget.AppBarLayout
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="wrap_content"
app:elevation="5dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
app:contentInsetEnd="5dp"
app:contentInsetLeft="15dp"
app:contentInsetRight="5dp"
app:contentInsetStart="15dp"
app:theme="@style/AppTheme.Toolbar"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:contentInsetStartWithNavigation="15dp"
app:titleTextColor="@color/colorWhite"
tools:targetApi="lollipop">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerInParent="true"
android:layout_gravity="start"
android:gravity="center"
android:text=""
android:textAllCaps="false"
android:textColor="@color/colorWhite"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="RelativeOverlap" />
<TextView
android:id="@+id/toolbar_student_details"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="end"
android:gravity="center"
android:text=""
android:textAllCaps="false"
android:textColor="@color/colorWhite"
android:textSize="16sp"
tools:ignore="RelativeOverlap" />
<Spinner
android:id="@+id/toolbar_student_details_spinner"
android:spinnerMode="dropdown"
android:layout_width="120dp"
android:backgroundTint="@color/colorWhite"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="end"
android:textAllCaps="false"
android:textColor="@color/colorWhite"
android:textSize="16sp"
tools:ignore="RelativeOverlap"
android:visibility="gone"
>
</Spinner>
<ImageView
android:id="@+id/admin_image"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:contentDescription="@string/app_name"
android:visibility="gone" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
Fragament code:
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup
container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView=
inflater.inflate(R.layout.fragment_staff_fragment_admin,
container, false);
setHasOptionsMenu(true);
ButterKnife.bind(this, rootView);
return rootView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
getBaseActivity().getMenuInflater().inflate(R.menu.menu_main,
menu);
SearchView searchView;
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager)getBaseActivity().
getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search)
.getActionView();
assert searchManager != null;
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getBaseActivity().getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
// listening to search query text change
searchView.setOnQueryTextListener(new
SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// filter recycler view when query submitted
mAdapter.getFilter().filter(query);
return false;
}
@Override
public boolean onQueryTextChange(String query) {
// filter recycler view when text is changed
mAdapter.getFilter().filter(query);
return false;
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_search) {
return true;
}
return super.onOptionsItemSelected(item);
}
Upvotes: 3
Views: 5108
Reputation: 204
In my app, I've several fragments inside a ViewPager + TabLayout. I don't understand how you can basically filter the RecyclerView realtime. To me it seems that your concept is just filtering once, i.e. as long as you don't call the method again, the list will not be filtered. Do you have some further insights?
Upvotes: 0
Reputation: 677
You should listen to changes in the Activity
and send the result to your Fragment
as your SearchView
is inside the Activity
( in the custom Toolbar
). One of the problems you may be facing is that the searchview is null when you are calling it.
I recommend doing this through your ViewModel
if you are using Android Architecture Components and the MVVM pattern as follows:
// listening to search query text change
searchView.setOnQueryTextListener(new
SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//filter the data in step 2
return false;
}
@Override
public boolean onQueryTextChange(String query) {
// filter data in step 2
return false;
}
});
inside your Activity:
...
@Override
public boolean onQueryTextSubmit(String query) {
//filter the data
viewModel.filterData(query);
return false;
}
...
inside your ViewModel:
public List<String> listOfData = getListOfData();
public LiveData<List<String>> searchResults = new MutableLiveData(listOfData);
// filter list of data when query submitted
public void filterData(String query) {
//filter outside of your RecyclerView Adapter through your listOfData variable
searchResults.value = getFilter().filter(query);
}
public LiveData<List<String>> getSearchResults() {
return searchResults;
}
by setting the result on your LiveData
through searchResults.value
you can listen to it change directly from your Fragment
, thus completing the communication between your Activity
and your Fragment
RecyclerView
through this variable in step 3.
ViewModel
variable inside your Fragment
& update the Adapterinside your Fragment
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.getSearchResults().observe(this, { searchResults->
Log.w("onActivityCreated()", "new search list received :" +searchResults)
mAdapter.updateList(searchResults)
listItemsAdapter.notifyDataSetChanged()
});
}
With these changes, you're filtering from the Activity SearchView
and sending the results to the Fragment RecyclerView
which should work. If you are using another pattern, the important thing is to send the query from your Activity
to your Fragment
instead of listening in your Fragment
only.
If you aren't using these yet, I recommend taking a look at AAC with MVVM. You can find more info in the Android Developers Documentation about these concepts.
Hope this helped, good luck.
Upvotes: 0