Anonymous_pj Anonymous_pj - 1 month ago 15
Android Question

How to implement AutoCompleteTextView within onQueryTextChange function of SearchView in actionbar

I want to implement an AutoCompleteTextView within the onQueryTextChange function of searchView, so that I get a suggestion list when I start typing in the search. How can I implement it?

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_search, menu);
MenuItem item = menu.findItem(R.id.menu_search);

final SearchView searchView = (SearchView)item.getActionView();

final LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, buildings);
final android.support.v7.app.ActionBar actionBar = getSupportActionBar();

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
@Override
public boolean onQueryTextSubmit(String query)
{
return false;
}

@Override
public boolean onQueryTextChange(String newText)
{

AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.editText1);
textView.setAdapter(adapter);
adapter.getFilter().filter(newText);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}

Answer

EDITED

The Layout file, named activity_search.xml.

<FrameLayout
    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:id="@+id/nested_parentframe"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">

    <!-- HERE IS WHERE YOUR OTHER VIEWS SHOULD GO -->

    <android.support.v7.widget.Toolbar
        android:id="@+id/nested_toolbar_1"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="#ffffff" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="0dp"
            app:cardBackgroundColor="@android:color/transparent"
            app:cardElevation="0dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:layout_margin="5dp"
                android:layout_gravity="center"
                android:background="#ffffff">

                <android.support.v7.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#ffffff"
                    app:cardElevation="0dp"
                    app:cardPreventCornerOverlap="false">

                    <android.support.v7.widget.Toolbar
                        android:id="@+id/nested_toolbar_2"
                        android:layout_width="match_parent"
                        android:layout_height="56dp"
                        android:layout_marginTop="0dp"
                        android:layout_gravity="center" />

                </android.support.v7.widget.CardView>

            </LinearLayout>

        </android.support.v7.widget.CardView>

        <LinearLayout
            android:id="@+id/recyclerViewLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:background="#ffffff"
            android:orientation="vertical"
            android:visibility="gone">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/cardsList"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:dividerHeight="1dp"/>
        </LinearLayout>

    </LinearLayout>

</FrameLayout>

Here is the Menu where SearchView is placed, named search_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"
    xmlns:tools="http://schemas.android.com/tools">

    <item
        android:id="@+id/search_menu_item"
        android:icon="@drawable/ic_search_grey"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="yourpackage.ArrayAdapterSearchView"
        android:textSize="16sp"
        android:title="Search" />
</menu>

Here is a custom ArrayAdapter for the SearchView.

public class ArrayAdapterSearchView extends SearchView {

    private SearchView.SearchAutoComplete mSearchAutoComplete;

    public ArrayAdapterSearchView(Context context) {
        super(context);
        initialize();
    }

    public ArrayAdapterSearchView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    public void initialize() {
        mSearchAutoComplete = (SearchAutoComplete) findViewById(android.support.v7.appcompat.R.id.search_src_text);
        this.setAdapter(null);
        this.setOnItemClickListener(null);
    }

    @Override
    public void setSuggestionsAdapter(CursorAdapter adapter) {
        // don't let anyone touch this
    }

    public void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
        mSearchAutoComplete.setOnItemClickListener(listener);
    }

    public void setAdapter(ArrayAdapter<?> adapter) {
        mSearchAutoComplete.setAdapter(adapter);
    }

    public void setText(String text) {
        mSearchAutoComplete.setText(text);
    }

    public void setSelection(int position){
        mSearchAutoComplete.setSelection(position);
    }

    public String getText(){
        return mSearchAutoComplete.getText().toString();
    }
}

Here is the RecyclerView list item layout, named card_item.xml.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    card_view:cardCornerRadius="1dp">

    <TextView
        android:id="@+id/itemNametxt"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="left"
        android:text=""
        android:textStyle="normal" />

</android.support.v7.widget.CardView>

Inside your Custom Adapter write a function like this.

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter .CustomRecyclerHolder> {
    private Context context;
    private ArrayList<String> arrayList = null, stringArrayList;
    private OnItemClickListener listener;

    public CustomAdapter(Context context, ArrayList<String> items) {
        this.context = context;
        this.arrayList = items;
        this.stringArrayList = new ArrayList<String>();
        this.stringArrayList.addAll(items);
    }

    @Override
    public CustomAdapter.CustomRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_item, parent, false);

        return new CustomRecyclerHolder(itemView);
    }

    @Override
    public void onBindViewHolder(CustomAdapter.CustomRecyclerHolder holder, int position) {
        holder.item.setText(arrayList.get(position).toString());
    }

    public class CustomRecyclerHolder extends RecyclerView.ViewHolder{
        protected TextView item;

        public CustomRecyclerHolder(View v){
            super(v);
            item = (TextView) v.findViewById(R.id.itemNametxt);

            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        listener.onItemClick(item.getText().toString());
                    }
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return this.arrayList.size();
    }

    public void filter(String filterString) {
        filterString = filterString.toLowerCase(Locale.getDefault());
        arrayList.clear();//Your list of items
        if(filterString.length() == 0) {
            arrayList.addAll(stringArrayList);
            //stringArrayList - 2nd list of items
        }
        else {
            for(String item : stringArrayList){
                if(item.toLowerCase(Locale.getDefault()).contains(filterString)) {
                    arrayList.add(item );
                }
            }
        }
        notifyDataSetChanged();
    }

    public void setOnItemClickListener(OnItemClickListener listener){
        this.listener = listener;
    }

    public interface OnItemClickListener{
        public void onItemClick(String item);
    }
}

Finally the Activity. EDITED

public class ExampleActivity extends AppCompatActivity {

    private ArrayAdapterSearchView searchView;
    private LinearLayout recycleLayout;
    private ArrayList<String> stringList;
    private RecyclerView recyclerView;
    private CustomAdapter adapter;
    private Toolbar mToolbar1, mToolbar2;
    private FrameLayout frameLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        mToolbar1 = (Toolbar) findViewById(R.id.nested_toolbar_1);
        mToolbar2 = (Toolbar) findViewById(R.id.nested_toolbar_2);

        frameLayout = (FrameLayout) findViewById(R.id.nested_parentframe);

        setSupportActionBar(mToolbar2);
        getSupportActionBar().setTitle("Search");
        mToolbar1.setNavigationIcon(R.mipmap.ic_action_overflow);

        mToolbar2.setTitleTextColor(getResources().getColor(android.R.color.tertiary_text_light));

        recycleLayout = (LinearLayout) findViewById(R.id.recyclerViewLayout);

        recyclerView = (RecyclerView) findViewById(R.id.cardsList);
        recyclerView.setHasFixedSize(true);
        LinearLayoutManager llm = new LinearLayoutManager(this);
        llm.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(llm);

        getSupportActionBar().setDisplayShowHomeEnabled(true);

        String[] strArray = new String[]{"Item One", "Item Two", "Item Three", "Item Four", "Item Five"};
        //This is your String array
        for(int i = 0; i < strArray.length; i++){
            stringList.add(strArray[i]);
        }

        if(!stringList.isEmpty()){
            adapter = new CustomAdapter(this, stringList);
            recyclerView.setAdapter(adapter);

            recycleLayout.setVisibility(View.VISIBLE);

            adapter.setOnItemClickListener(new CustomAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(String item) {
                    searchView.setQuery(item, false);
                }
            });
        }
        else{
            recycleLayout.setVisibility(View.GONE);
        }       

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_menu, menu);

        MenuItem searchItem = menu.findItem(R.id.search_menu_item);

        searchView = (ArrayAdapterSearchView) MenuItemCompat.getActionView(searchItem);
        searchView.setLayoutParams(new ActionBar.LayoutParams(Gravity.LEFT));

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                if (query.length() != 0) {
                    if (null != adapter) {
                        adapter.filter(query.toString());//This will filter the RecyclerView
                        recyclerView.setVisibility(View.VISIBLE);
                    }
                }
                else{
                    recyclerView.setVisibility(View.GONE);
                }
                return false;
            }
        });

        searchView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String length = searchView.getText();
                searchView.setSelection(length.length());
            }
        });

        return true;
    }

}
Comments