Implementing SearchView in action bar - android

I need to create SearchView from my arrayList<String> and show the suggestions in the drop-down list same this
I look for tutorials that explain step by step how to build a SearchView in a action bar.
I have read the documentation and following the example google but it was not useful to me.
I have created the search
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/action_search"
android:title="Search"
android:icon="#android:drawable/ic_menu_search"
android:showAsAction="always"
android:actionViewClass="android.widget.SearchView" />
</menu>`
But I do not know how to set the parameters of the array of strings.
I tried to retrieve the result in a different Activity but not work.

It took a while to put together a solution for this, but have found this is the easiest way to get it to work in the way that you describe. There could be better ways to do this, but since you haven't posted your activity code I will have to improvise and assume you have a list like this at the start of your activity:
private List<String> items = db.getItems();
ExampleActivity.java
private List<String> items;
private Menu menu;
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.example, menu);
this.menu = menu;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();
search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));
search.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String query) {
loadHistory(query);
return true;
}
});
}
return true;
}
// History
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void loadHistory(String query) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// Cursor
String[] columns = new String[] { "_id", "text" };
Object[] temp = new Object[] { 0, "default" };
MatrixCursor cursor = new MatrixCursor(columns);
for(int i = 0; i < items.size(); i++) {
temp[0] = i;
temp[1] = items.get(i);
cursor.addRow(temp);
}
// SearchView
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
final SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();
search.setSuggestionsAdapter(new ExampleAdapter(this, cursor, items));
}
}
Now you need to create an adapter extended from CursorAdapter:
ExampleAdapter.java
public class ExampleAdapter extends CursorAdapter {
private List<String> items;
private TextView text;
public ExampleAdapter(Context context, Cursor cursor, List<String> items) {
super(context, cursor, false);
this.items = items;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
text.setText(items.get(cursor.getPosition()));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item, parent, false);
text = (TextView) view.findViewById(R.id.text);
return view;
}
}
A better way to do this is if your list data is from a database, you can pass the Cursor returned by database functions directly to ExampleAdapter and use the relevant column selector to display the column text in the TextView referenced in the adapter.
Please note: when you import CursorAdapter don't import the Android support version, import the standard android.widget.CursorAdapter instead.
The adapter will also require a custom layout:
res/layout/item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
You can now customize list items by adding additional text or image views to the layout and populating them with data in the adapter.
This should be all, but if you haven't done this already you need a SearchView menu item:
res/menu/example.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/search"
android:title="#string/search"
android:showAsAction="ifRoom"
android:actionViewClass="android.widget.SearchView" />
</menu>
Then create a searchable configuration:
res/xml/searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/search"
android:hint="#string/search" >
</searchable>
Finally add this inside the relevant activity tag in the manifest file:
AndroidManifest.xml
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value="com.example.ExampleActivity" />
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
Please note: The #string/search string used in the examples should be defined in values/strings.xml, also don't forget to update the reference to com.example for your project.

If anyone else is having a nullptr on the searchview variable, I found out that the item setup is a tiny bit different:
old:
android:showAsAction="ifRoom"
android:actionViewClass="android.widget.SearchView"
new:
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"
pre-android x:
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"
For more information, it's updated documentation is located here.

SearchDialog or SearchWidget ?
When it comes to implement a search functionality there are two suggested approach by official Android Developer Documentation.
You can either use a SearchDialog or a SearchWidget.
I am going to explain the implementation of Search functionality using SearchWidget.
How to do it with Search widget ?
I will explain search functionality in a RecyclerView using SearchWidget. It's pretty straightforward.
Just follow these 5 Simple steps
1) Add searchView item in the menu
You can add SearchView can be added as actionView in menu using
app:useActionClass = "android.support.v7.widget.SearchView" .
<menu 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"
tools:context="rohksin.com.searchviewdemo.MainActivity">
<item
android:id="#+id/searchBar"
app:showAsAction="always"
app:actionViewClass="android.support.v7.widget.SearchView"
/>
</menu>
2) Set up SerchView Hint text, listener etc
You should initialize SearchView in the onCreateOptionsMenu(Menu menu) method.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem searchItem = menu.findItem(R.id.searchBar);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setQueryHint("Search People");
searchView.setOnQueryTextListener(this);
searchView.setIconified(false);
return true;
}
3) Implement SearchView.OnQueryTextListener in your Activity
OnQueryTextListener has two abstract methods
onQueryTextSubmit(String query)
onQueryTextChange(String newText
So your Activity skeleton would look like this
YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{
public boolean onQueryTextSubmit(String query)
public boolean onQueryTextChange(String newText)
}
4) Implement SearchView.OnQueryTextListener
You can provide the implementation for the abstract methods like this
public boolean onQueryTextSubmit(String query) {
// This method can be used when a query is submitted eg. creating search history using SQLite DB
Toast.makeText(this, "Query Inserted", Toast.LENGTH_SHORT).show();
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.filter(newText);
return true;
}
5) Write a filter method in your RecyclerView Adapter.
Most important part. You can write your own logic to perform search.
Here is mine. This snippet shows the list of Name which contains the text typed in the SearchView
public void filter(String queryText)
{
list.clear();
if(queryText.isEmpty())
{
list.addAll(copyList);
}
else
{
for(String name: copyList)
{
if(name.toLowerCase().contains(queryText.toLowerCase()))
{
list.add(name);
}
}
}
notifyDataSetChanged();
}
Relevant link:
Full working code on SearchView with an SQLite database in this Music App

For Searchview use these code
For XML
<android.support.v7.widget.SearchView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/searchView">
</android.support.v7.widget.SearchView>
In your Fragment or Activity
package com.example.user.salaryin;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.example.user.salaryin.Adapter.BusinessModuleAdapter;
import com.example.user.salaryin.Network.ApiClient;
import com.example.user.salaryin.POJO.ProductDetailPojo;
import com.example.user.salaryin.Service.ServiceAPI;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class OneFragment extends Fragment implements SearchView.OnQueryTextListener {
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
ArrayList<ProductDetailPojo> arrayList;
BusinessModuleAdapter adapter;
private ProgressDialog pDialog;
GridLayoutManager gridLayoutManager;
SearchView searchView;
public OneFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.one_fragment,container,false);
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Please wait...");
searchView=(SearchView)rootView.findViewById(R.id.searchView);
searchView.setQueryHint("Search BY Brand");
searchView.setOnQueryTextListener(this);
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
layoutManager = new LinearLayoutManager(this.getActivity());
recyclerView.setLayoutManager(layoutManager);
gridLayoutManager = new GridLayoutManager(this.getActivity().getApplicationContext(), 2);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.setHasFixedSize(true);
getImageData();
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.one_fragment, container, false);
return rootView;
}
private void getImageData() {
pDialog.show();
ServiceAPI service = ApiClient.getRetrofit().create(ServiceAPI.class);
Call<List<ProductDetailPojo>> call = service.getBusinessImage();
call.enqueue(new Callback<List<ProductDetailPojo>>() {
#Override
public void onResponse(Call<List<ProductDetailPojo>> call, Response<List<ProductDetailPojo>> response) {
if (response.isSuccessful()) {
arrayList = (ArrayList<ProductDetailPojo>) response.body();
adapter = new BusinessModuleAdapter(arrayList, getActivity());
recyclerView.setAdapter(adapter);
pDialog.dismiss();
} else if (response.code() == 401) {
pDialog.dismiss();
Toast.makeText(getActivity(), "Data is not found", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<List<ProductDetailPojo>> call, Throwable t) {
Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
pDialog.dismiss();
}
});
}
/* #Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
getActivity().getMenuInflater().inflate(R.menu.menu_search, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
searchView.setQueryHint("Search Product");
searchView.setOnQueryTextListener(this);
}*/
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
newText = newText.toLowerCase();
ArrayList<ProductDetailPojo> newList = new ArrayList<>();
for (ProductDetailPojo productDetailPojo : arrayList) {
String name = productDetailPojo.getDetails().toLowerCase();
if (name.contains(newText) )
newList.add(productDetailPojo);
}
adapter.setFilter(newList);
return true;
}
}
In adapter class
public void setFilter(List<ProductDetailPojo> newList){
arrayList=new ArrayList<>();
arrayList.addAll(newList);
notifyDataSetChanged();
}

Related

Duplicating menu items everytime it open in overflow options menu

I am trying to add two menu items in action bar with xml code:
<?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/search"
android:title="#string/search"
android:icon="#drawable/ic_action_search"
app:showAsAction="ifRoom"
/>
<item
android:id="#+id/share"
android:title="#string/share"
android:icon="#drawable/ic_action_share"
app:showAsAction="ifRoom"
/>
And my java code is :
package com.erprakash.contacts;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
//import android.net.Uri;
import android.provider.ContactsContract;
//import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import java.util.ArrayList;
//import java.util.Comparator;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<Contact> arrayList = new ArrayList<>();
int img_id = R.drawable.image1;
String name ;
String number ;
private int id;
private Contact contact;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Tool bar setting
//toolbar end
// Reading Contacts -----Working
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE NOCASE ASC");
if (phones != null) {
while (phones.moveToNext())
{
name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
number = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
id = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO_FILE_ID));
if(id == 0){
contact = new Contact(number, name, img_id);
}else {
contact = new Contact(number, name, id);
}
arrayList.add(contact);
}
phones.close();
}
/**
name = getResources().getStringArray(R.array.person_name);
number = getResources().getIntArray(R.array.mobile_number);
int c = 0;
for(String Name: name)
{
Contact contact = new Contact(number[c],Name,img_id[c]);
c++;
arrayList.add(contact);
}
**/
recyclerView = (RecyclerView)findViewById(R.id.rvMainContennt);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
adapter = new ContactAdapter(arrayList);
recyclerView.setAdapter(adapter);
}
//-------------Toolbar------------
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int res_id = item.getItemId();
if(res_id == R.id.search)
{
Toast.makeText(this.getApplicationContext(),"You have seleted search option",Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public boolean onPrepareOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
}
In preview the design appears correct :
But in running state :
And on clicking the option menu :
Every time when i open the option menu the content gets duplicated and goes on , i have searched solution for this but i didn't get it anywhere . help me out....Thanks in advance
Remove onPrepareOptionsMenu().
#Override
public boolean onPrepareOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
Update onCreateOptionsMenu() as below:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
If you want to show menu item always on Toolbar, then update menu_main.xml 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/search"
android:title="#string/search"
android:icon="#drawable/ic_action_search"
app:showAsAction="always" />
<item
android:id="#+id/share"
android:title="#string/share"
android:icon="#drawable/ic_action_share"
app:showAsAction="always" />
</menu>
When I ran into this issue I called menu.clear() inside of onPrepareOptionsMenu and that fixed it.
If your wondering why I didn't switch to onCreateOptionsMenu it is because I need to use onPrepareOptionsMenu for reasons.

How to set the MenuItemClickListener for a SearchView at a secondary Toolbar

i am trying for hours to setup a simple android.support.v7.widget.SearchView in a bottom (secondary) android.support.v7.widget.ToolBar.
I am already using another Toolbar up top set up as an ActionBar, so i cannot use the onCreateOptionsMenu callback on activity, instead i have to set up an OnMenuItemClickListener() . I have read the Android SearchView Tutorial, this tutorial about Toolbars.
Related Code,
simplified HomepageActivity
package something.somethingelse.activities;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SearchView.OnCloseListener;
import android.support.v7.widget.SearchView.OnQueryTextListener;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Toast;
public class HomepageActivity extends AppCompatActivity {
protected static final String TAG = "HomepageActivity";
private Toolbar mTopToolbar;
private Toolbar mBottomToolbar;
private FloatingActionButton mFab;
private Context mContext;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTopToolbar = (Toolbar) findViewById(R.id.topToolbar);
setSupportActionBar(mTopToolbar);
mBottomToolbar = (Toolbar) findViewById(R.id.bottomToolbar);
mBottomToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
SearchManager searchManager = (SearchManager) HomepageActivity.this.getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = null;
if (menuItem != null) {
Log.d(TAG, "menuItem != null");
searchView = (SearchView) menuItem.getActionView();
}
if (searchView != null) {
Log.d(TAG, "searchView != null");
searchView.setSearchableInfo(searchManager.getSearchableInfo(HomepageActivity.this.getComponentName()));
}
searchView.setOnCloseListener(new OnCloseListener() {
#Override
public boolean onClose() {
mBottomToolbar.setVisibility(View.GONE);
return false;
}
});
searchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String arg0) {
Log.d(TAG, "Submited: "+arg0);
return false;
}
#Override
public boolean onQueryTextChange(String arg0) {
Log.d(TAG, "Changed: "+arg0);
return false;
}
});
return false;
}
});
mBottomToolbar.inflateMenu(R.menu.bottom_toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_bar, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
simplified Homepage Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:guide="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v7.widget.Toolbar
android:id="#+id/topToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#color/white"
guide:elevation="4dp"
android:minHeight="?attr/actionBarSize"
guide:theme="#style/Toolbar_Theme" >
<ImageView
android:id="#+id/ivAb_logo"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="58dp"
android:paddingTop="10dp"
android:src="#drawable/generic_logo" />
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/topToolbar" >
<RelativeLayout
android:id="#+id/homepage_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/homepage_background"
android:orientation="vertical" >
<android.support.v7.widget.Toolbar
android:id="#+id/bottomToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/primaryDark"
guide:elevation="4dp" />
</RelativeLayout>
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="220dp"
android:layout_height="fill_parent"
android:layout_gravity="start"
android:background="#60BBBBBB"
android:choiceMode="singleChoice"
android:divider="#FFFFFF"
android:dividerHeight="1px" />
</android.support.v4.widget.DrawerLayout>
menu bottom_toolbar.xml
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:guide="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:title="#string/search"
android:icon="#drawable/ic_search_white"
guide:actionViewClass="android.support.v7.widget.SearchView"
guide:showAsAction="always">
</item>
searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="#string/search"
android:label="#string/app_name"
/>
AndroidManifest.xml related part
<activity
android:name="something.somethingelse.activities.HomepageActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/Theme.Default" >
<intent-filter>
<action android:name="something.somethingelse.activities.HomepageActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
If i run it like that, i get a SearchView but without my android:icon="#drawable/ic_search_white", instead i get the google SearchView icon, if i tap it i get a nice edit text, with clear and search functions, but no matter what i input or press, NONE of the Log.d inside the Toolbar.OnMenuItemClickListenergets fired up. (I cannot post images because of reputation).
If i use android:actionViewClass="android.support.v7.widget.SearchView" instead of guide:actionViewClass="android.support.v7.widget.SearchView" i get my android:icon="#drawable/ic_search_white" , if i tap it, i get an NPE on searchView.setOnCloseListener(new OnCloseListener() { because searchView is null .
I tried doing whats on this related question here, and this but no success so far.
Updated 23/09/15
I could not find any good solution, so, since i only wanted to get the SearchView item i decided to hack into it like so:
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState==null){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.dlHomepageSpace, HomepageFragment.newInstance(mLanguage), HOMEPAGE_BUTTONS_TAG);
fragmentTransaction.commit();
}
mSearchState = SearchState.NOSEARCH;
mBottomToolbar = (Toolbar) findViewById(R.id.bottomToolbar);
mBottomToolbar.inflateMenu(R.menu.bottom_toolbar);
// Here we set the search view toolbar functions
if(mBottomToolbar.getMenu().size() > 0){
SearchManager searchManager = (SearchManager) HomepageActivity.this.getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = mBottomToolbar.getMenu().getItem(mBottomToolbar.getMenu().size()-1);
mSearchView = (SearchView) searchMenuItem.getActionView();
if (mSearchView != null) {
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(HomepageActivity.this.getComponentName()));
}
mSearchView.setOnCloseListener(new OnCloseListener() {
#Override
public boolean onClose() {
Log.d(TAG, "onClose");
mBottomToolbar.getMenu().getItem(mBottomToolbar.getMenu().size()-1).collapseActionView();
switchToFab();
return false;
}
});
MenuItemCompat.setOnActionExpandListener(searchMenuItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
Log.d(TAG, "onMenuItemActionExpand");
return true; // KEEP IT TO TRUE OR IT DOESN'T OPEN !!
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
Log.d(TAG, "onMenuItemActionCollapse");
switchToFab();
return true;
}
});
}
}
#Override
protected void onNewIntent(Intent intent) {
Log.d(TAG, "onNewIntent");
if(isSearchAction(intent)){
ArrayList<Detail> list = (ArrayList<Detail>) getListData(intent.getStringExtra(SearchManager.QUERY));
if(list.isEmpty()){
Toast.makeText(this, R.string.no_search_results_en, Toast.LENGTH_LONG).show();
}
} else {
ExtendedListFragment searchFragment = (ExtendedListFragment) getSupportFragmentManager().findFragmentByTag(HOMEPAGE_SEARCH_TAG);
mResultsList = list;
mSearchState = SearchState.SEARCH_LIST_SCREEN;
if(searchFragment==null){
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.dlHomepageSpace, ExtendedListFragment.newInstance(list), HOMEPAGE_SEARCH_TAG);
fragmentTransaction.commit();
} else {
searchFragment.setDetailList(list);
}
}
}
}
private boolean isSearchAction(Intent intent) {
Log.d(TAG, "handleIntent");
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
Log.d(TAG, "ACTION_SEARCH");
return true;
}
return false;
}
In essence, i just look into the toolbar, and obtain the one and only Item into it, i cast it as a MenuItem and then i get the SearchView as the ActionView of the MenuItem.
Like that it works and i do not have to use setOnMenuItemClickListener() . When i tap in the view, i can type into it (i do not need a mSearchView.OnQueryTextListener but, i have seen it working) , when i press the magnifying glass on the keyboard i get the onNewIntent() call working.

Programmatically setting SearchView to be open

I have a SearchView in my activity using this code:
import java.util.List;
import android.app.Activity;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;
import android.widget.SearchView;
import android.widget.TextView;
public class MainActivity extends Activity implements
SearchView.OnQueryTextListener {
private SearchView mSearchView;
private TextView mStatusView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.activity_main);
mStatusView = (TextView) findViewById(R.id.status_text);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) searchItem.getActionView();
setupSearchView(searchItem);
return true;
}
private void setupSearchView(MenuItem searchItem) {
if (isAlwaysExpanded()) {
mSearchView.setIconifiedByDefault(false);
} else {
searchItem.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
mSearchView.setOnQueryTextListener(this);
}
public boolean onQueryTextChange(String newText) {
mStatusView.setText("Query = " + newText);
return false;
}
public boolean onQueryTextSubmit(String query) {
mStatusView.setText("Query = " + query + " : submitted");
return false;
}
public boolean onClose() {
mStatusView.setText("Closed!");
return false;
}
protected boolean isAlwaysExpanded() {
return false;
}
}
menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_search"
android:actionViewClass="android.widget.SearchView"
android:icon="#android:drawable/ic_menu_search"
android:showAsAction="always"
android:title="Search"/>
</menu>
and layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal" />
</LinearLayout>
What I want to do is when the Activity is started, I want the SearchView to start off opened. It starts off "closed" like this:
but I want it to be "open" like this:
Anyway I can do this? Thanks
It's at the top of the documentation: http://developer.android.com/reference/android/widget/SearchView.html
setIconifiedByDefault(false)
Edit:
In order to have it collapsible but expanded at the start then programatically expand it in onCreateOptionsMenu with
searchItem.expandActionView();
and you'll probably need
mSearchView.requestFocus();

How to Add to ListView Dynamically Using Action Bar Button

I want to dynamically add items to my ListView in Android. However, I want this to be done when the user presses an action bar button. From what I have found, to do this, one needs to extend ListActivity and ActionBarActivity which Android doesn't support. How do I do this otherwise. Here is my code for MainActivity (which right now only extends ActionBarActivity):
import java.util.ArrayList;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
public class MainActivity extends ActionBarActivity {
/** Items entered by the user is stored in this ArrayList variable */
ArrayList<String> list = new ArrayList<String>();
/** Declaring an ArrayAdapter to set items to ListView */
ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,list);
setListAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_new:
addListElement();
return true;
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void addListElement() {
// TODO Auto-generated method stub
}
}
In your activity_main.xml add a listview.. then use like below...
ListView lv = (ListView) findViewById(R.id.listViewId);
lv.setAdapter(adapter);
remove setListAdapter(adapter);
private void addListElement(String value) {
list.add(value);
adapter.notifyDataSetChanged();
}
OR
private void addListElement(String value) {
adapter.add(value);
}

ActionBarSherlock pulldown menu with tabs

I'm trying to implement ActionBarSherlock with tabs but allow a pulldown menu in the action bar on certain tabs. I've read that the only way to get both is to create a custom actionProvider for the pulldown. Here is the code I wrote to implement:
menu_with_dropdown.xml (with a separate overflow menu that is working fine)
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/motivate_picker"
android:showAsAction="always"
android:title="Right Here"
android:actionProviderClass=".ActionBarSpinner">
</item>
<item
android:id="#+id/menu_item"
android:showAsAction="always"
android:icon="#drawable/action_bar_plus_icon">
<menu>
<item android:id="#+id/menu_1"
android:title="#string/menu_1" />
<item android:id="#+id/menu_2"
android:title="#string/menu_2" />
<item android:id="#+id/menu_3"
android:title="#string/menu_3"/>
<item android:id="#+id/menu_4"
android:title="#string/menu_4"/>
</menu>
</item>
</menu>
The tab fragment that uses this pulldown inflates it here
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu,inflater);
menu.clear();
getSherlockActivity().getSupportActionBar().setDisplayShowTitleEnabled(false);
getSherlockActivity().getSupportMenuInflater().inflate(R.menu.menu_with_dropdown, menu);
}
ActionBarSpinner.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import com.actionbarsherlock.view.ActionProvider;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SubMenu;
public class ActionBarSpinner extends ActionProvider implements
MenuItem.OnMenuItemClickListener {
Context context_;
public ActionBarSpinner(Context context) {
super(context);
context_ = context;
}
#Override
public View onCreateActionView() {
LayoutInflater layoutInflater = LayoutInflater.from(context_);
View view = layoutInflater.inflate(R.layout.actionbar_menu,null);
//return view; //Will have formatted pulldown but not register clicks for submenu
return null; //Will register clicks and expand submenu but not be formatted as desired
}
#Override
public boolean onPerformDefaultAction() {
return false;
}
#Override
public boolean hasSubMenu() {
return true;
}
#Override
public void onPrepareSubMenu(SubMenu subMenu) {
MenuItem item = subMenu.add("Test1");
item.setOnMenuItemClickListener(this);
item = subMenu.add("Test3");
item.setOnMenuItemClickListener(this);
item = subMenu.add("Test2");
item.setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
return true;
}
}
actionbar_menu.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
style="#android:style/Widget.ActionButton"
android:clickable="true">
<TextView
android:id="#+id/motivate_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Friend Picker"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="#drawable/switcher_arrow"/>
</LinearLayout>
So the problem arises when I call onCreateActionView() in ActionBarSpinner. If I return the inflated View of actionbar_menu.xml, it never expands the subMenu that I created. If I return null in onCreateActionView(), the submenu expands when I click on it but it doesn't have the custom layout I made (it actually shows nothing). Any help would be appreciated.
you have to return null in order for the onPrepareSubMenu() being called.
Then, all these setups in onCreateActionView() need to go in to onCreateOptionsMenu() in probably MainActivity.
For example,
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
// Override the default language icon to the language is being used
MenuItem mI = menu.findItem(R.id.menu_locale);
Locale locale = Locale.getDefault();
String locLan = locale.getLanguage();
if (locLan.equals(Locale.CHINESE.getLanguage())) {
mI.setIcon(R.drawable.insready);
} else if (locLan.equals(Locale.ENGLISH.getLanguage())) {
mI.setIcon(R.drawable.ic_action_locale_en);
} else if (locLan.equals(Locale.FRENCH.getLanguage())) {
mI.setIcon(R.drawable.ic_action_search);
}
return true;
}

Categories

Resources